🍉 类型断言
as
和<>
都可以用来类型推断,但是尖括号格式会与 react
中 JSX
产生语法冲突,因此我们更推荐使用 as
语法。
🥥 as
有些情况下 ts
并不能正确或者准确得推断类型,这个时候可能产生不必要的警告或者报错
const person = {};
person.name = 'randy'; // Error: 'name' 属性不存在于 ‘{}’
person.age = 20; // Error: 'age' 属性不存在于 ‘{}’
解决方法:添加类型断言
interface Person {
name: string;
age: number;
}
const person = {} as Person;
person.name = 'randy';
person.age = 20;
🥥 <>
如果代码中使用 document.getElementById
,ts
只知道这将返回某种 HTMLElement
,但我们确定页面将始终具有具有给定 ID 的 HTMLCanvasElement
。
- 通过上述的
as
断言
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
- 通过
<>
断言
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
🍉 双重断言
const a = expr as any as T;
虽然类型断言是有强制性的,但并不是万能的,因为一些情况下也会失效:
const x = "hello" as number;
// Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
先把类型断言为 any
再接着断言为你想断言的类型就能实现双重断言
const x = "hello" as any as number;
🍉 非空断言
在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符
!
可以用于断言操作对象是非null
和非undefined
类型。具体而言,x!
将从x
值域中排除null
和undefined
。
先来看个示例:
function sayHello(name: string | undefined) {
let sname: string = name; // Error
}
对于以上代码,TypeScript 编译器会提示一下错误信息:
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
要解决上述问题,我们可以简单加个条件判断:
function sayHello(name: string | undefined) {
let sname: string;
if (name) {
sname = name;
}
}
使用这种方案,问题是解决了。但有没有更简单的方式呢?答案是有的,就是使用 TypeScript 2.0 提供的非空断言操作符:
function sayHello(name: string | undefined) {
let sname: string = name!;
}
🍉 确定赋值断言
使用场景:定义了变量, 没有赋值, 就使用,则会报错
🥥 Example1
let num: number;
console.log(num); // error Variable 'num' is used before being assigned.
let num!: number;
console.log(num); // undefined
🥥 Example2
let x: number;
initialize();
// Variable 'x' is used before being assigned.
console.log(x); // Error
function initialize() {
x = 10;
}
let x!: number;
initialize();
console.log(x); // 10
function initialize() {
x = 10;
}
🍉 类型守卫
类型守卫说白了就是缩小类型的范围,常用的有
- 类型判断:
typeof
- 实例判断:
instanceof
- 属性判断:
in
- 字面量相等判断:
==
,===
,!=
,!==
🥥 类型判断:typeof
function test(input: string | number) {
if (typeof input == 'string') {
// 这里 input 的类型「收紧」为 string
} else {
// 这里 input 的类型「收紧」为 number
}
}
🥥 实例判断:instanceof
class Foo {}
class Bar {}
function test(input: Foo | Bar) {
if (input instanceof Foo) {
// 这里 input 的类型「收紧」为 Foo
} else {
// 这里 input 的类型「收紧」为 Bar
}
}
🥥 属性判断:in
interface Foo {
foo: string;
}
interface Bar {
bar: string;
}
function test(input: Foo | Bar) {
if ('foo' in input) {
// 这里 input 的类型「收紧」为 Foo
} else {
// 这里 input 的类型「收紧」为 Bar
}
}
🥥 字面量相等判断:==
, ===
, !=
, !==
type Foo = 'foo' | 'bar' | 'unknown';
function test(input: Foo) {
if (input != 'unknown') {
// 这里 input 的类型「收紧」为 'foo' | 'bar'
} else {
// 这里 input 的类型「收紧」为 'unknown'
}
}