类型推断
类型推断,指不须要指定变量类型或者函数的返回值类型,TypeScript能够依据一些简略的规定推断其类型。
类型推断是有方向的,要留神辨别从左向右和从右向左两种推断的不同援用。
根底类型推断
根底类型推断发送在初始化变量、设置默认参数和决定函数返回值时
let num = 3; // 推断为number类型let str = 'string'; // 推断为string类型let bool = true; // 推断为boolean类型let u = undefined; // 推断为boolean类型let n = null; // 推断为null类型num = 'xman'; // Type '"xman"' is not assignable to type 'number'.str = 18; // Type '18' is not assignable to type 'string'.bool = '60' // Type '"60"' is not assignable to type 'boolean'.u = 1; // Type '1' is not assignable to type 'undefined'.n = true; // Type 'true' is not assignable to type 'null'.
留神:
在TypeScript中,应用const和let申明的类型,默认推断出的类型是不同的,如:
{ let str = 'this is string'; // 推断为string类型 let num = 1; // 推断为number类型 let bool = true; // 推断为boolean类型}{ const str = 'this is string'; // 字符串字面量类型'this is string' const num = 1; // 数字字面量类型 1 const bool = true; // 布尔字面量类型 true}
解释: 当咱们将一个字面量类型申明为常量,咱们就不能再对其进行批改了,因而将其类型推断为赋值的字面量类型,是一种比拟正当的设计。
而应用 let 申明的字面量类型,因为咱们还领有将其批改为该类型其余字面量的权力,因而TypeScript将其类型转换为了赋值字面量类型的父类型,这种设计也是合乎编程预期的。
咱们将 TypeScript 的字面量子类型转换为父类型的这种设计称之为 "literal widening"
,也就是字面量类型的拓宽。
如果定义的时候没有赋值, 不论之后有没有赋值,都会被推断为 any
类型 而齐全不被类型查看:
let a; // 推断为any类型a = 'hello';a = false;a = 100;a = undefined;a = null;a = {};
最佳通用类型推断
最佳通用类型,顾名思义,就是对于某些表达式的最合适的通用类型
计算通用类型的算法会思考所有的候选类型,并给出一个兼容所有候选类型的类型。
let a = ['xman', 18, true]; // a被推断为(string|number|boolen)[] 联结类型a[3] = 2; // Type 'null' is not assignable to type 'string | number | boolean'.
以上,数组里蕴含多个类型string、number、boolean, TypeScript就推断出兼容所有类型的通用类型(string | number | boolen)[] 联结类型
上下文类型推断
TypeScript类型推论也可能依照相同的方向进行。 这被叫做“按上下文归类”。按上下文归类会产生在表达式的类型与所处的地位相干时
上下文归类会在很多状况下应用到。 通常蕴含函数的参数,赋值表达式的左边,类型断言,对象成员和数组字面量和返回值语句。 上下文类型推断则是从左向右的类型推断。
上下文类型还充当最佳公共类型中的候选类型。
依据参数的类型,推端出返回值的类型
// 依据参数的类型,推端出返回值的类型也是numberfunction add (x: number, y: number) { return x + y;}let sum = add (1, 2); // 推断出sum的类型也是number sum = '123'; // Type '"123"' is not assignable to type 'number'.// y 被推断为number | undefinedfunction add1 (x: number, y = 2) { return x + y; }add1(1, '2'); // Argument of type '"2"' is not assignable to parameter of type 'number | undefined'.
函数参数类型/返回值通过赋值来推断
type Adder = (x: number, y: number) => number;let add: Adder = (x, y) => x + y;add('1', 2); // Argument of type '"1"' is not assignable to parameter of type 'number'. let sum = add(1, 2); // 推断出sum的类型也是number sum = '123'; // Type '"123"' is not assignable to type 'number'.
以上代码中, add的类型是Adder,它能让add的参数x, y是number类型, 返回值也推断为number类型。
以上是一个从左向右流动类型的示例。
如果你创立一个函数,并且函数参数为一个回调函数,雷同的赋值规定也实用于它。从 argument 至 parameter 只是变量赋值的另一种模式。type Adder = (x: number, y: number) => number; function fn(add: Adder) { return add(1, 2);}fn((x, y) => { x = 'hello'; // Type '"hello"' is not assignable to type 'number'. return x + y; })
对象成员
对于对象字面量const obj = { name: 'xman', age: 18 };// obj类型被推断为 { name: string; age: number; }obj.name = false; // Type 'false' is not assignable to type 'string'.
解构中:
const obj = { name: 'xman', age: 18 };let { name } = obj;name = true; // Type 'true' is not assignable to type 'number'.const a = ['xman', 18];let [x, y] = a; // 此时x, y都被推断为'string | number'y = false; // Type 'false' is not assignable to type 'string | number'.
类型断言
interface IAdd { (x: number, y: number): number; }const add = function (x, y) { return x + y; } as IAdd;add(1, 2); // Argument of type '"2"' is not assignable to parameter of type 'number'.
以上代码中咱们给匿名函数指定了类型上下文IAdd, 从而推断出参数x, y类型都是number类型。
最初, 如有谬误,欢送各位大佬指导!感激!
参考资料
https://www.typescriptlang.org/docs/handbook/type-inference.html#handbook-content
https://jkchao.github.io/typescript-book-chinese/typings/typeInference.html