一、基本数据类型
-
boolean
let test1: boolean = true; let test2: boolean = new Boolean(); //报错,因为Boolean不是布尔值 let test3: boolean = Boolean(1); //正确,直接调用Boolean,可以返回一个boolean类型。
-
number
let hex: number = 10;
-
string
let myAge: string = 'woshi';
-
void,没有空值,可以修饰没有任何返回值的函数
function handle(): void { }
-
null、undefined,是所有类型的子类型,可以复制给其他类型的变量
let u: undefined = undefined; let n: null = null;
-
any 任意值
-
是所有类型的子类型,允许被赋值为任意类型。
-
变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型。
-
类型推断:没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
//报错,声明指定类型后,不能赋值其他类型 let myFavoriteNumber: string = 'seven'; myFavoriteNumber = 7; //正确 let myFavoriteNumber: any = 'seven'; myFavoriteNumber = 7; //调用任何方法、属性 let anyThing: any = 'Tom'; console.log(anyThing.myName); anyThing.setName('Jerry'); //声明的时候,未指定其类型,被识别为任意值类型 let newdata;
-
-
类型推断:没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
let myFavoriteNumber = 'seven'; myFavoriteNumber: string = 'seven'; myFavoriteNumber = 7; //报错,类型推论将myFavoriteNumber定义成一个字符串,不能赋值number类型
二、对象类型—接口
- 定义对象的类型
- 约束函数:传递参数对象具体类型,格式、返回值要以什么类型返回
- 限制变量对象:类型、格式
-
接口修饰的对象,对象得跟接口一样的数据格式、类型。
interface LabelledValue { label: string; label2: number; } function printLabel(labelledobj: LabelledValue) { console.log(labelledobj.label); console.log(labelledobj.size); //编译报错,因为接口中没有size。 } let myObj = {size: 10, label: "Size 10 Object", label2: 233}; //编译报错,因为接口中没有size。 printLabel(myObj);
-
可选属性
-
接口中使用
可索引类型
去描述(约束)对象。(可以对比接口方式去声明数组用到的可索引类型) -
只读属性
-
只读: 对象变量声明时给只读属性赋值,而不是第一次给只读属性赋值的时候
interface Person { readonly id: number; name: string; age?: number; [propName: string]: any; } let tom: Person = { //报错 因为接口中的id是只读,声明时必须给其赋值 name: 'Tom', gender: 'male' }; tom.id = 89757; //报错 id,只能读,不能重新赋值
-
有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用
readonly
定义只读属性interface Person { readonly id: number; name: string; age?: number; [propName: string]: any; } let tom: Person = { id: 89757, name: 'Tom', gender: 'male' }; tom.id = 9527; //报错 id,只能读,不能重新赋值
-
三、数组的类型
数组声明(定义)方式:
- 类型 + 方括号: number[]
- 数组泛型:Array
- 用接口表示数组
- 类数组:如arguments
- any在数组中的应用
-
类型 + 方括号:
let fibonacci: number[] = [1, '1', 2, 3, 5]; //报错,因为不能出场除了number之外的类型
-
数组泛型:
let fibonacci: Array<number> = [1,2,3,4,5];
-
接口中使用
可索引的类型
去描述 (约束) 数组:interface NumberArray { [index: number]: number } let fibonacci: NumberArray = [1,2,3,4,5];
-
类数组: 不是数组类型, 比如:arguments,不能用普通的方式描述。
function sun() { let args: number[] = arguments; //报错,arguments是类数组,不能用普通的方式描述。 } //例子1:可以通过接口的方式声明变量接收arguments。 //在这个例子中,我们除了约束当索引的类型是数字时,值的类型必须是数字之外,也约束了它还有 length 和 callee 两个属性。 function sum() { let args: { [index: number]: number; length: number; callee: Function; } = arguments; } //例子二:IArguments 是 TypeScript 中定义好了的类型,用来声明类数组 function sum() { let args: IArguments = arguments; }
-
any在数组中的应用: 表示数组中允许出现任意类。
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];
四、函数的类型
-
函数声明:
-
函数表达式:
-
方式一:
let mySum = function (x: number, y: number): number { return x + y; };
-
方式二:用 => 来定义函数,左边是参数类型,右边是返回值类型(区别es6中的箭头函数)。
//1.定义变量 add,指定类型为 (x: number, y: number)=> number let add:(x: number, y: number)=> number //2.给变量赋值函数,其符合上面定义的函数类型 add = (arg1: number, arg2: number) => arg1 + arg2 //结合1.2,实现函数的定义 let add(X: number, y: number)=> number = (x: number, y:number) => { return x + y; }
-
-
默认参数、可选参数
//设置参数age可以穿也可以不传 function getInfo(name: string,age?: number): string { return `${name}----${age}` } getInfo("jiangjiang"); //设置参数age,当不传的时候默认赋值20 function getPerson(name: String,age: number=20): string { return `${name}----${age}` }
-
函数重载
-
重载允许一个函数接受不同数量或者类型的参数时i,作出不同的处理。
###//例:对比联合类型传承、函数重载优缺点 //联合类型传承:有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。 function reverse(x: number | string): number | string { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); } } //函数重载 function reverse(x: number): number; function reverse(x: string): string; function reverse(x: number | string): number | string { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); } }
-
五、联合类型
-
约束变量的类型不局限一种类型,可以是多种类型。
-
使用
|
分隔每个类型。let myFavoriteNumber: string | number; myFavoriteNumber = 'seven'; myFavoriteNumber = 7; //允许 myFavoriteNumber 的类型是 string 或者 number,但是不能是其他类型。
-
-
TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
//案例1 function getLength(something: string | number): number { return something.length; //报错,因为length不是string跟number的共有属性 } //案例2 function getString(something: string | number): string { return something.toString();//正确,toString是他们的共有方法 } //案例3 interface Cat { name: string; run(): void; } interface Fish { name: string; swim(): void; } function getName(animal: Cat | Fish) { return animal.name; //正确,name是Cat跟Fish共有属性 }
-
联合类型的变量在赋值的时候,会根据类型推论规则推断出一个类型。
let myFavoriteNumber: string | number; myFavoriteNumber = 'seven'; console.log(myFavoriteNumber.length); //正确,因为赋值“seven”时,变量被推断为string类型,string具有length属性。 myFavoriteNumber = 7; console.log(myFavoriteNumber.length); //报错,因为赋值7时,变量被推断为number类型,number不具有length属性
-
六、类型断言
-
作用、语法
-
作用:可以用来手动指定一个值的类型。
-
语法:
//写法一: 值 as 类型 //写法二: <类型>值
-
-
应用场景:
-
//案例一:断言优点 interface Cat { name: string; run(): void; } interface Fish { name: string; swim(): void; } function isFish(animal: Cat | Fish) { //即使swin不是联合类型Cat、Fish共有方法,通过断言成Fish,就可以骗过编译器 if (typeof (animal as Fish).swim === 'function') { return true; } return false; } //案例二:缺点 interface Cat { name: string; run(): void; } interface Fish { name: string; swim(): void; } function swim(animal: Cat | Fish) { //编译通过,但是运行时报错,因为参数tom: Cat并不存在swim方法。 (animal as Fish).swim(); } const tom: Cat = { name: 'Tom', run() { console.log('run') } }; swim(tom);
-
子类也可以断言成相应的父类
-
使用类型断言:判断传入函数的类型是不是Child1
class Child1 extends Error { code: number = 0; } class Child2 extends Error { statusCode: number = 200; } function isChild1(error: Error) { //可以将父类Error断言具体子类Child1:这样就可以访问到Child1的code属性,若不断言则报错,因为Error不存在code属性。 if(typeof(error as Child1).code == 'number') { return true; }else { return false; }
}
+ 使用instanceof:判断传入函数的类型是不是Child1 ```typescript class Child1 extends Error { code: number = 0; } class Child2 extends Error { statusCode: number = 200; } function isChild1(error: Error) { if(error instanceof child1) { return true; }else { return false; } }
-
断言类型跟instanceof区别:instanceof只能用于判断继承的父子关系,不能用来判断接口。
interface Child1 extends Error { code: number; } interface Chilid2 extends Error { statusCode: number; } function isChild1(error: Error) { //报错,因为Child1是一个接口,无法使用instaceof,这边应该使用断言类型。 if(error instanceof child1) { return true; }else { return false; }
-
-
将任何一个类型断言为any:as any
//编译报错,因为window对象不存在foo; window.foo = 1; //any类型,访问任何属性都是允许的。 (window as any).foo = 1;
-
将any断言为一个具体的类型
function getCacheData(key: string): any { return (window as any).cache[key]; } interface Cat { name: string; run(): void; } //getCacheData,它的返回值是 any,此时可以将其断言成具体的Cat类型方便后续操作。 const tom = getCacheData('tom') as Cat; tom.run();
-
-
区别:类型断言、类型转换
-
类型转换:会真的影响到变量的类型。
-
类型断言:只会影响 TypeScript 编译时的类型,类型断言语句在编译结果中会被删除。
function toBoolean(something: any): boolean { return Boolean(something); } //类型转换:将number类型转成boolean类型 toBoolean(1);
-
-
区别:类型断言、类型约束
-
类型断言:父子关系可以互相断言,即:
父类型 as 子类型
、子类型 as 父类型
。interface Animal { name: string; } interface Cat { name: string; run(): void; } const animal: Animal = { name: 'tom' }; let tom = animal as Cat; //正确,因为他们存在父子关系
-
interface Animal { name: string; } interface Cat { name: string; run(): void; } const animal: Animal = { name: 'tom' }; let tom: Cat = animal; //报错,Animal 可以看作是 Cat 的父类,当然不能将父类的实例赋值给类型为子类的变量。
-
-
区别:类型断言、泛型
interface Cat { name: string; run(): void; } //类型断言 function getCacheData(key: string): any { return (window as any).cache[key]; } const tom = getCacheData('tom') as Cat; tom.run(); //泛型,通过给 getCacheData 函数添加了一个泛型 <T>,我们可以更加规范的实现对 getCacheData 返回值的约束,这也同时去除掉了代码中的 any,是最优的一个解决方案。 function getCacheData<T>(key: string): T { return (window as any).cache[key]; } const tom = getCacheData<Cat>('tom'); tom.run();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。