TypeScript 作为JavaScript 的超集,在继承JavaScript的数据类型基础上扩展了一些新的类型。
数据类型注解
1继承自JavaScript的基本类型
javascript 的基本类型有 number,string,boolean,null,undefined,symbol.
先看其中四种:
let bar0: number;
let bar1: string;
let bar2: boolean;
let bar3: symbol;
bar0 = 0xf00d;
bar1 = 'hello';
bar2 = true;
bar3 = Symbol.for('word');
bar3 = 'word';//Type '"word"' is not assignable to type 'symbol'
再看null和undefined。
在TypeScript中,null和undefined各种拥有自己的类型 null和undefined,类似void。
null和undefined是其他所有类型的子类型,这意味着,可以给其他类型赋予null或者undefined。
let bar0: number;
let bar1: string;
bar0 = null;
bar1 = undefined;
2 继承自JavaScript的复杂数据类型
2.1 Array 数组类型注解
不同于JavaScript,TypeScript 不仅规定了数组类型本身,还支持数组元素类型的定义,类似Java中的泛型。语法上有两种实现方式。如果存在jsx,则推荐第一种方式
let boolArray: boolean[]
boolArray = [true, false]
boolArray = ['false'] //Type 'string' is not assignable to type 'boolean'
let stringArray: Array<string | boolean>
stringArray = [true, 'hello', 'word']
stringArray = [123456]//Type 'number' is not assignable to type 'string | boolean'.
2.2 object
object 代表了非原始类型。原始类型是指 number,string,boolean,symbol,null,undefined 等
let obj: object
obj = {
a: 123,
b:'hello'
}
obj = Symbol.for('word')//Type 'symbol' is not assignable to type 'object'.
3. TypeScript 扩展的类型
3.1 元组 tuple
python3中的元组是定以后不能修改。而在TypeScript中,元组类型表示一个已知元素数量和类型的数组,各元素的类型不必相同,类型和数量是确定的。
let arr: [boolean, string, symbol]
arr = [true, 'hello', Symbol.for('word')]
arr = [true]//error 元素数量errorerror
arr = [true,'hello',123456]//Type 'number' is not assignable to type 'symbol'.
3.2 枚举 enum
枚举类型是对javaScript的补充
enum Color{
Red,
Green,
Blue='blue'
}
console.log(Color)
let color1 = Color.Red //0
let color2 = Color.Blue //blue
// 编译结果如下
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color["Blue"] = "blue";
})(Color || (Color = {}));
console.log(Color);
var color1 = Color.Red; //0
var color2 = Color.Blue; //blue
上述代码结果解读,重点是Color.Red 为0。
// 赋值表达式,返回的值是等号右边的值,所以会返回0
Color["Red"] = 0
//最终生成的结果如下
{
0: "Red"
1: "Green"
Red: 0
Green: 1
Blue: "blue"
}
3.3 Any 类型
有些变量的类型在编程阶段是不清楚的,这些变量是动态获取的,比如用户输入或者第三库传入,这时候,我们希望编译器在编译的时候对这些变量不进行校验。这种情形可以采用 any 类型。
let arg:any;
arg = 'hello world';
arg = Symbol.for('hello');
尤其常见的常见是,对现有javaScript代码进行重写,允许可选择的移除编译时检查。
Object有相似的作用,就像它在其它语言中那样。 但是 Object类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法:
let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
3.4 Void类型
Void,同any表示任何类型不同,Void表示没有任何类型,常见的场景为函数返回值注解。
function foo(name:string): void{
console.log(name)
}
void 类型只能赋值null或 undefined
let arg: void;
arg = null;
arg = undefined;
arg = 'hello';//Type '"hello"' is not assignable to type 'void'
3.5 Never类型
never类型表示的是那些永不存在的值的类型。 例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。
never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 即使 any也不可以赋值给never。
never 作用示例,参考尤雨溪尤大的例子
在没有开启 strictNullChecks 的前提下使用 never 避免出现新增了联合类型没有对应的实现,目的就是写出类型绝对安全的代码。
interface Foo {
type: 'foo'
}
interface Bar {
type: 'bar'
}
type All = Foo | Bar
//在 switch 当中判断 type,TS 是可以收窄类型的 (discriminated union):
function handleValue(val: All) {
switch (val.type) {
case 'foo':
// 这里 val 被收窄为 Foo
break
case 'bar':
// val 在这里是 Bar
break
default:
// val 在这里是 never
const exhaustiveCheck: never = val
break
}
}
注意在 default 里面我们把被收窄为 never 的 val 赋值给一个显式声明为 never 的变量。如果一切逻辑正确,那么这里应该能够编译通过。但是假如后来有一天你的同事改了 All 的类型:
type All = Foo | Bar | Baz
然而他忘记了在 handleValue 里面加上针对 Baz 的处理逻辑,这个时候在 default branch 里面 val 会被收窄为 Baz,导致无法赋值给 never,产生一个编译错误。所以通过这个办法,你可以确保 handleValue 总是穷尽 (exhaust) 了所有 All 的可能类型。