Narrowing
TS的变量可能是多种类型,需要确定类型,在去做相应的处理
ts
function padLeft(padding: number | string, input: string): string {
return ' '.repeat(padding) + input;
// Error: Argument of type 'string | number' is not assignable to parameter of type 'number'.
// Type 'string' is not assignable to type 'number'.
}
改进后
ts
function padLeft(padding: number | string, input: string): string {
if (typeof padding === 'number') {
return ' '.repeat(padding) + input;
}
return padding + input;
}
typeof
type guards
typeof
来判断基本类型,返回对应类型的字符串
- "string"
- "number"
- "bigint"
- "boolean"
- "symbol"
- "undefined"
- "object"
- "function"
Truthiness narrowing
下面都是 false:
- 0
- NaN
- "" (the empty string)
- 0n (the bigint version of zero)
- null
- undefined
Equality narrowing
switch
语句和相等比较(===
, !==
, ==
, 和 !=
)会缩窄类型,保证类型相同; 下面示例,if
判断会保证x和y的类型相同,所以当x === y
为 true 时,x和y的类型都是 string
ts
function example(x: string | number, y: string | boolean) {
if (x === y) {
// We can now call any 'string' method on 'x' or 'y'.
// (method) String.toUpperCase(): string
x.toUpperCase();
// (method) String.toLowerCase(): string
y.toLowerCase();
} else {
// (parameter) x: string | number
console.log(x);
// (parameter) y: string | boolean
console.log(y);
}
}
The in
operator narrowing
in
用来判断是否是Object里面的成员
ts
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ('swim' in animal) {
return animal.swim();
}
return animal.fly();
}
instanceof
narrowing
instanceof
用来判断是否某个类型的实例
ts
function logValue(x: Date | string) {
if (x instanceof Date) {
// (parameter) x: Date
console.log(x.toUTCString());
} else {
// (parameter) x: string
console.log(x.toUpperCase());
}
}
Assignments
赋值符号=
会去缩窄类型
ts
let x = Math.random() < 0.5 ? 10 : 'hello world!'; // let x: string | number;
x = 1; // let x: number;
console.log(x);
x = 'goodbye!'; // let x: string
console.log(x);
Control flow analysis
Using type predicates
pet is Fish
is our type predicate in this example
ts
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
let pet = getSmallPet();
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
Assertion functions
Discriminated unions
用联合类型的成员来告知 Object 当前是什么类型
ts
interface Shape {
kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
function handleShape(shape: Shape) {
// oops!
if (shape.kind === 'rect') {
// Error: This comparison appears to be unintentional because the types '"circle" | "square"' and '"rect"' have no overlap.
// ...
}
}
// 配合non-null断言使用`!`
function getArea(shape: Shape) {
if (shape.kind === 'circle') {
return Math.PI * shape.radius! ** 2;
}
}
另一种方式:联合类型 + 多Interface
ts
interface Circle {
kind: 'circle';
radius: number;
}
interface Square {
kind: 'square';
sideLength: number;
}
type Shape = Circle | Square;
The never
type
// TODO
Exhaustiveness checking
// TODO