TS支持JS中所有的数据类型,并且做了一定的扩展:
Tuple
- 元组可以看成是写死长度的
array,与array不同,tuple并不需要成员类型相同。 - 获取元组中已知索引的元素,返回值会具有正确的类型。
- 元组只支持访问存在的索引。
type myTuple = [string, number];
let mt: myTuple = ['1',2];
let mt0 = mt[0]; // string
let mt2 = mt[2]; // Error: Tuple type 'myTuple' of length '2' has no element at index '2'
enum
- 编译:
enum Color {
Red,
Green,
}
// 会被编译成
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
})(Color || (Color = {}));
- 枚举类型的值默认从0开始计数,可手动指定成员的值。
enum Color {
Red ,
Yellow = 2,
Blue,
}
let aNumber: number = Color.Red; // 0
let aColor: Color = Color.Blue; // 3
let aString: string = Color.Blue; // Type 'Color' is not assignable to type 'string'
Unknown
定义: 我们可能并不需要描述那些当我们写代码时并不知道的变量类型,比如
动态内容(来自于用户输入或者我们可能故意想要接收所有类型的值)。在这种情况下,我们通过类型unknown想要告诉编译器和未来的维护者,这个变量可能是任何值。
let notSure: unknown;
notSure = 4;
notSure = 'something';
- 如果我们有一个
unkown类型的变量,我们可以通过类型检查(typeof checks)比较检查(comparison checks)或者类型守卫(type guards)来缩小类型可能的范围来进行类型约束。
let maybe: unknown;
let aNumber: number;
let aString: string;
aNumber = maybe; // Error: Type 'unknown' is not assignable to type 'number'
// typeof check
if (typeof maybe === 'string') {
aString = maybe;
}
// comparison check
if (maybe === 'maybe') {
aString = maybe;
}
let dontknow: unknown = {};
if (typeof dontknow === 'function') {
console.log(dontknow) // let dontknow: Function
}
console.log(dontknow) // let dontknow: unknown
Any
- 一些场景下,值的类型本身就获取不到或者声明它的类型的实在花销太大。比如来自于非ts模块的值或者一些第三方库的值。 此时,我们通过给值一个
any类型来选择性退出类型检查。 在处理老的js时,这点很有效,我们可以在编译时选择性的进入/退出类型检查。
let thirdPartyFn = function(): any {}
let aNumber: number = thirdPartyFn(); // 此时没有类型检查
- 不同于类型
unknown,any类型的值,可以访问其任意属性而不用关心这行属性存在与否。
let looselyType: any;
looselyType.fixed();
let strictType: unknown;
strictType.fixed(); // Error: Object is of type 'unknown'
any类型会在对象内传播,其内部的值都是any类型。
let looselyType: any = {};
looselyType.a.fixed();
虽然
any看起来很方便,但是却完全没有起到类型检查的作用,如果动因都没了,干嘛还要用ts呢,所以除非必要,不要使用any类型。
Void
Void有点类似于any的反义,没有类型就是它的类型,常用于函数的返回值。
function justWarn():void {}
justWarn();
- 声明一个
void类型的变量没啥意义,因为你只能赋值null/undefined类型的值给它(还得在--strictNullChecks没有开启的情况下)
Null和Undefined
- ts中有
null类型和undefiend类型,就像void类型一样,他们独自使用时,并没有什么用。 - 默认情况下,
null和undefined是任意类型的子类型,也就是说null和undefined类型可以分配给任意类型的变量。 - 开启
--strictNullChecks选项后,null和undefined类型只能被赋值给unknownany和他们自己的类型(注意其实也可以赋值给void类型),要是万一想要支持null/undefined类型,可以使用联合类型(union types),比如string | null | undefined。
Never
never类型代表该值的类型永远不可能出现,比如一个永远不会返回的函数(函数内抛错或死循环不结束)。never类型是任意类型的子类型,可以被分配给任意类型,但任意类型都无法分配给never类型(包括any类型也不行,never可以分配给自己)。
// A function returning 'never' cannot have a reachable end point
function neverEnd(): never {
throw new Error('func never end');
}
function infiniteLoop(): never {
while(true) {
// 返回值是never表示函数永远无法执行完
}
}
Object
- 类型
object指非基本类型(常见五小+symbol) - 这个类型基本用不到
Type assertions
- 有时你会遇到这样的情况:你对于这个实体的类型知道的比ts当前定义的类型更加清除。
类型断言(type assertion)就是用来告诉编译器:相信我,我知道自己在干嘛。此时,编译器就不会执行特殊的类型检查。- 类型断言有两种语法:
as和(<>),JSX中只支持第一种。
let someValue: unknown;
console.log((someValue as string).length);
annotation
ts类型不要使用
Boolean等数据类型大写形式