1️⃣ 类型约束与编译结果的对比
2️⃣ 类型约束
仅仅需要在变量,函数的参数,函数的返回值位置上加上 **:类型** 即可
ts 在很多场景中可以完成类型推导,如果 ts 无法完成类型推到且开发者没有约束类型,ts 则默认为 any,any 表示任意类型,对该类型,ts 不进行类型检查。
add 函数中即使没有为函数的返回值做类型约束,但是 ts 依旧会类型推导为 number 因为, add 的参数都已经约束为 number,return 又是 a + b 所有 ts 就可以推导到 add 的返回值为 number 类型
如果 ts 无法推导出类型会显示三个点
2️⃣ 编译结果对比
1️⃣ 基本类型约束
// numberlet a: number = 10;// stringlet b: string = '10';// booleanlet c: boolean = true;// 数组let arr: number[] // 约束为数字类型的数组let arr1: Array<number>let arr2: object[] // 约束为字符串类型的数组let arr3: Array<object>// 对象let f: object = {};// null 和 undefined// null 和 undefined 可以赋值给其他类型let g: number = null;let h: string = undefined;// 通过添加 "strictNullChecks": true 可以获得更严格的空类型检查,让 null 和 undefined 只能赋值给自身
1️⃣ 其他类型约束
// 联合类型:多种类型任选其一let a: number | string;if (typeof a === 'number') {// 联合类型可以配合类型保护来使用// 类型保护:当对某个变量进行类型判断之后,在判断的语句中便可以确定它的确切类型// typeof 可以触发类型保护,但是只能触发简单的类型保护,复杂类型判断不了}// void 类型:通常用于约束函数的返回值,表示该函数没有任何返回。function b(): void {console.log(0);}// never 类型:通常用于约束函数的返回值,表示该函数永远不会结束。function c(msg: string): never {throw new Error(msg)}// 字面量类型let d: "A" | 1; // 强力约束 d 只能赋值为字符串 "A" 或 数字 1,不能赋值为其它值。let e: { // 对象字面量约束,表示 e 被约束为一个对象,且对象 e 里必须有一个 name 属性,值为字符串,必须有一个 age 属性,值为数字name: stringage: number}e = {name: "A",age: 1}// 元祖类型( Tuple ):表示一个固定长度的数组,数组的每一项都有类型约束。let f: [string, number, boolean]; // 约束 f 为一个数组,数组只能有三项且必须为 string, number, boolean 类型f = ['A', 1, true]// any 类型:any 类型可以绕过类型检测,可以赋值为任意类型let g: any;(g as []).push() // 使用类型断言为某种指定的类型g = 1console.log(g); // 1// unknown 类型:未知类型,和 any 都是 TS 的 “顶部类型”// unknown 类型是 any 的类型安全版本。每当你想使用 any 时,应该先试着用 unknown。// 在 any 允许我们做任何事的地方,unknown 的限制则大得多。// 在对 unknown 类型的值执行任何操作之前,必须先通过以下方法限定其类型:1.类型断言 2.相等 3.类型防护let u: unknown;(u as string).split // 使用类型断言为某种指定的类型u = 1console.log(u); // 1https://www.html.cn/web/javascript/19308.html
2️⃣ any 和 unknown
1️⃣ 类型别名
// 类型别名 - 对已知的一些类型定义名称// type 类型名 = 类型约束type Job = "前端" | "开发"type User = {name: strinage: numberjob: Job}let i: User = {name: 'chen',age: 18,job: '前端'}// 类型别名直接约束函数type funRestrain = {(a: number, b: number): boolean}function fun(a: number, b: number): boolean {return true;}let func: funRestrain;func = fun;// 约束回调函数type Condition = (a: number) => booleanfunction fun(callback: Condition) { }// 约束函数let fun1: Conditionfun1 = (b: number) => { return true }// 类型别名交叉使用 - 使用 & 符号type A = {a: number}type B = {b: number}type C = {// a: string 类型别名的成员可以交叉,这里结果为 a: number & stringc: number} & A & Blet d: C = {a: 1,b: 2,c: 3,}
1️⃣ 类型断言
类型断言:用来告诉解析器变量的实际类型。
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法:
let someValue: any = "this is a string";let strLength: number = (<string>someValue).length;
另一个为 as 语法:
let someValue: any = "this is a string";let strLength: number = (someValue as string).length;
两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在TypeScript里使用JSX时,只有as语法断言是被允许的。
1️⃣ 函数的相关约束
2️⃣ 函数重载
在函数实现之前,对函数的多种情况进行声明。
// 函数重载function fun(a: number, b: number): number; // 重载条件function fun(a: string, b: string): string; // 重载条件function fun(a: number | string, b: number | string): number | string {if (typeof a === 'number' && typeof b === 'number') {return a * b;}else if (typeof a === 'string' && typeof b === 'string') {return a + b;}throw new Error('类型不符合标准')}fun(1, 2) // 符合第一条重载fun('1', '2') // 符合第一条重载fun(1, '2') // 没有与之相匹配的重载 - 报错
2️⃣ 可选参数
可以在某些参数后加上问号,表示该参数可以不用传递。
// 可选参数function fun(a: number, b: number, c?: number) {if (c) {return a + b + c;} else {return a + b;}}fun(1, 2, 3)fun(1, 2)
2️⃣ 参数默认值
约束类型后直接赋值或者使用 js 的参数默认值方式
// 参数的默认值function fun(a: number, b: number, c: number = 0) {return a + b + c;}fun(1, 2, 3)fun(1, 2)
