Typescript 那些好用的技巧

1、 类型断言

类型断言可以明确的告诉 TypeScript 值的详细类型,

在某些场景, 我们非常确认它的类型, 即使与 typescript 推断出来的类型不一致. 那我们可以使用类型断言. 

语法如下: 

< 类型 >

as 类型

// 推荐使用这种语法. 因为容易跟泛型, react 中的语法起冲突

举个例子, 如下代码,  padding 值可以是 string , 也可以是 number, 虽然在代码里面写了 Array(), 我们明确的知道, padding 会被parseint 转换成 number 类型, 但类型定义依然会报错. 

function padLeft ( value : string , padding : string | number ) {

// 报错: Operator ‘+’ cannot be applied to

// types ‘string | number’ and ‘number’

return Array ( padding + 1 ). join ( ” “ ) + value ;

}

解决方法, 使用类型断言. 告诉 typescript 这里我确认它是 number 类型, 忽略报错. 

function padLeft ( value : string , padding : string | number ) {

// 正常

return Array ( padding as number + 1 ). join ( ” “ ) + value ;

}

但是如果有下面这种情况, 我们要写很多个 as 么? 

function padLeft ( value : string , padding : string | number ) {

console . log (( padding as number ) + 3 );

console . log (( padding as number ) + 2 );

console . log (( padding as number ) + 5 );

return Array (( padding as number ) + 1 ). join ( ‘ ‘ ) + value ;

}

2、 类型守卫

类型守卫有以下几种方式, 简单的概括以下

  • typeof:  用于判断 “number”,”string”,”boolean”或 “symbol” 四种类型. 

  • instanceof : 用于判断一个实例是否属于某个类

  • in: 用于判断一个属性/方法是否属于某个对象

  • 字面量类型保护

上面的例子中, 是 string | number 类型, 因此使用 typeof 来进行类型守卫. 例子如下: 

function padLeft ( value : string , padding : string | number ) {

if ( typeof padding === ‘number’ ) {

console . log ( padding + 3 ); //正常

console . log ( padding + 2 ); //正常

console . log ( padding + 5 ); //正常

//正常

return Array ( padding + 1 ). join ( ‘ ‘ ) value ;

}

if ( typeof padding === ‘string’ ) {

return padding + value ;

}

}

相比较 类型断言 as , 省去了大量代码. 除了 typeof , 我们还有几种方式, 下面一一举例子. 

  • instanceof :用于判断一个实例是否属于某个类

class Man {

handsome = ‘handsome’ ;

}

class Woman {

beautiful = ‘beautiful’ ;

}

function Human ( arg : Man | Woman ) {

if ( arg instanceof Man ) {

console . log ( arg . handsome );

console . log ( arg . beautiful ); // error

} else {

// 这一块中一定是 Woman

console . log ( arg . beautiful );

}

}

  • in : 用于判断一个属性/方法是否属于某个对象

interface B {

b : string ;

}

interface A {

a : string ;

}

function foo ( x : A | B ) {

if ( ‘a’ in x ) {

return x . a ;

}

return x . b ;

}

  • 字面量类型保护

有些场景, 使用 in, instanceof, typeof 太过麻烦. 这时候可以自己构造一个字面量类型. 

type Man = {

handsome : ‘handsome’ ;

type : ‘man’ ;

};

type Woman = {

beautiful : ‘beautiful’ ;

type : ‘woman’ ;

};

function Human ( arg : Man | Woman ) {

if ( arg . type === ‘man’ ) {

console . log ( arg . handsome );

console . log ( arg . beautiful ); // error

} else {

// 这一块中一定是 Woman

console . log ( arg . beautiful );

}

}

3、双重断言

有些时候使用 as 也会报错,因为 as 断言的时候也不是毫无条件的. 它只有当S类型是T类型的子集,或者T类型是S类型的子集时,S能被成功断言成T. 

所以面对这种情况, 只想暴力解决问题的情况, 可以使用双重断言. 

function handler ( event : Event ) {

const element = event as HTMLElement ;

// Error: ‘Event’ 和 ‘HTMLElement’

中的任何一个都不能赋值给另外一个

}

如果你仍然想使用那个类型,你可以使用双重断言。首先断言成兼容所有类型的any

function handler ( event : Event ) {

const element = ( event as any ) as HTMLElement ;

// 正常

}

三. 巧用 typescript 支持的 js 最新特性优化代码