TypeScript入门-枚举、类型推论
枚举
使用枚举可以定义一些具有名字的数字常量,和在C语言中一样都是使用关键字enum
enum Direction { Up = 1, Down = 1<<2, Left, Right }
注意:一个枚举类型可以有多个枚举成员,每个枚举成员都有一个对应的数字值,这个数字值可以是常数或者是计算得出的值。当满足下列条件时,枚举成员的数字值被认为是常数
- 不具有初始化函数并且之前的枚举成员是常数。 在这种情况下,当前枚举成员的值为上一个枚举成员的值加1。 但第一个枚举元素是个例外。 如果它没有初始化方法,那么它的初始值为
0
。 - 枚举成员使用常数枚举表达式初始化。 常数枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。 当一个表达式满足下面条件之一时,它就是一个常数枚举表达式:
- 数字字面量
- 引用之前定义的常数枚举成员(可以是在不同的枚举类型中定义的) 如果这个成员是在同一个枚举类型中定义的,可以使用非限定名来引用。
- 带括号的常数枚举表达式
+
,-
,~
一元运算符应用于常数枚举表达式+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
二元运算符,常数枚举表达式做为其一个操作对象 若常数枚举表达式求值后为NaN
或Infinity
,则会在编译阶段报错。
例如:
enum Direction { //常数 Up, //0 Down = 3, //3 Left = Down + 4, //7 Right, //8 //计算的值 center = [1,2,3,4].length //4 }
注意:在枚举类型中每个枚举成员对应的数字值必须是唯一的,不能重复。如果有重复,则会取最后一个
enum Direction { //常数 Up, //0 Down = 3, //3 Left = Down + 4, //7 Right, //8 //计算的值 center = [1,2,3].length //3 } console.log(Direction.Down); //3 console.log(Direction[3]); //center
枚举类型中是包含双向映射的,即(value -> name)和(name -> value)
console.log(Direction.Down); //3 console.log(Direction[3]); //Down
常数枚举
当访问枚举值时,为了避免生成多余的代码和间接引用,可以使用常数枚举。 常数枚举是在enum关键字前使用const修饰符。
常数枚举只能使用常数枚举表达式并且不同于常规的枚举的是它们在编译阶段会被删除。 常数枚举成员在使用的地方被内联进来。 这是因为常数枚举不可能有计算成员。
const enum Direction { //常数 Up, //0 Down = 3, //3 Left = Down + 4, //7 Right, //8 //计算的值 center = [1,2,3,4].length //error }
类型推论
TypeScript里,在有些没有明确指出类型的地方,类型推论会帮助提供类型
let x = 'qwe';
变量x的类型被推断为string。 这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时
最佳通用类型
有时需要从多个类型中推断,这时会根据这些类型推断出一个最合适的通用类型
let x = [0, 1, null];
为了推断x
的类型,我们必须考虑所有元素的类型。 这里有两种选择: number
和null
。 计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型
但是有时没有一个类型能够作为所有候选类型的类型,如果没有找到最佳通用类型的话,类型推论的结果是空对象类型,{}
。 因为这个类型没有任何成员,所以访问其成员的时候会报错。
一般要明确的指出类型
上下文类型
TypeScript类型推论也可能按照相反的方向进行。 这被叫做“按上下文归类”。按上下文归类会发生在表达式的类型与所处的位置相关时。
上下文归类会在很多情况下使用到。 通常包含函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句
window.onmousedown = function(mouseEvent) { console.log(mouseEvent.buton); //error };
之所以会报错,是因为类型检查器会根据赋值号=右边来推断参数mouseEvent的类型
如果上下文类型表达式包含了明确的类型信息,上下文的类型被忽略。 重写上面的例子:
window.onmousedown = function(mouseEvent: any) { console.log(mouseEvent.buton); };
这个函数表达式有明确的参数类型注解,上下文类型被忽略。 这样的话就不报错了,因为这里不会使用到上下文类型
参考资料:
TypeScript中文网 · TypeScript——JavaScript的超集