进阶技巧
类型推断
- 基础推断
let name = "pro"; // 推断为string
let age = 24; // 推断为number
let x; // 没有初始化的变量会被推断为any
- 最佳通用类型推断
在推断时,考虑所有元素类型,找到兼容所有候选类型的最佳类型
let arr = [1, 2, 3, "pro"]; // 推断为 (string | number)[]
- 上下文类型推断
通常包含函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句。
// 函数的返回值被推断为number
function add(a: number, b: number) {
return a + b;
}
类型断言
- 尖括号语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
- as语法
let someValue: any = "this is as string";
let strLength: number = (someValue as string).length;
类型缩小
类型缩小是通过一定的方式,缩小变量的类型范围,针对不同类型的变量,处理逻辑可能不同
例如,官方文档中给出的一个padLeft函数的例子,这个函数在输入字符串的左侧填充一定的padding,若padding为string,则直接拼接,若padding为number, 则填充padding数量的空格
function padLeft(padding: number | string, input: string): string {
if (typeof padding === 'number') {
return new Array(padding + 1).join(" ") + input;
// return " ".repeat(padding) + input;
}
return padding + input;
}
typeof类型保护
如上面这段代码所示,通过typeof限定处理逻辑
- 真值缩小
使用if、&&、||、否定表达式等进行真值检查
function multiplyAll(
values: number[] | undefined,
factor: number
): number[] | undefined {
if (!values) {
return values;
} else {
return values.map(x => x * factor);
}
}
这里过滤了使 if语句为假的所有类型,如0、NaN、空字符串、null、undefined等
- 等值缩小
使用相等判断缩小检查类型,可以利用三等号同时判断类型的相同
function example(x: number | string, y: boolean | string) {
if (x === y) {
x.toUpperCase();
y.toUpperCase();
} else {
console.log(x);
console.log(y);
}
}
这里因为x和y有只可能同为string,直接用三等号判断就可确定为string类型
in运算符缩小
type Fish = {
swim: () => {}
}
type Bird = {
fly: () => {}
}
function move(animal: Fish | Bird) {
if ("fly" in animal) {
return animal.fly;
}
return animal.swim;
}
instance运算符缩小
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toLocaleString());
} else {
console.log(x.toUpperCase());
}
}
- 类型谓词
Type Predicate是TypeScript中的一种特殊语法,帮助TS编译器确定运行时的变量类型
type Fish = {
swim: () => {}
}
type Bird = {
fly: () => {}
}
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined
}
通过这个isFish函数,可以确定对象是否为Fish类型,在具体代码逻辑中做到类型缩小
extends
- 继承类
class Animal {
name: string;
constructor(_name: string) {
this.name = _name;
}
}
class Dog extends Animal {
constructor(_name: string) {
super(_name);
}
bark() {
console.log(this.name + " is barking.");
}
}
- 泛型约束
function identity<T extends { length: number }>(arg: T): T {
console.log(arg.length);
return arg;
}
identity(3); // error
identity({ length: 1, name: 'pro' }); // ok
- 条件类型
SomeType extends OtherType ? TrueType : FalseType;
interface Animal {
live(): void
}
interface Dog extends Animal {
bark(): void
}
type t1 = Dog extends Animal ? number : string; // t1 这里就是number类型了
let variable: t1 = 1;