TS入门-基础类型

615 阅读4分钟

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类型一样,他们独自使用时,并没有什么用。
  • 默认情况下,nullundefined是任意类型的子类型,也就是说nullundefined类型可以分配给任意类型的变量。
  • 开启--strictNullChecks选项后,nullundefined类型只能被赋值给unknown any和他们自己的类型(注意其实也可以赋值给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 等数据类型大写形式