探索 TypeScript 类型注解 - 数据类型

Exploring TypeScript Type Annotations - Built-in Types

关于

本文由 WowBar 团队首发于 GitHub

作者: zhilidali

欢迎来到 《探索 TypeScript 类型注解》 系列教程。
开篇我们(重新)认识了 TypeScript,本篇探索 TypeScript 的原生数据类型。

目录

  1. 使用类型注解

  2. 基础类型

  3. 引用类型

正文

1 使用类型注解

let foo = 'TS';
let bar: boolean = foo; // Error: Type 'string' is not assignable to type 'boolean'.ts(2322)

类型注解

Type Annotations

语法: type。如 :boolean

作用 :约定变量的数据类型。如约定 bar 为布尔值。

好处

  1. 静态编译时检查类型。如编译器会警告 Type 'string' is not assignable to type 'boolean'
  2. 作为文档。在 VSCode 中将光标移到第二行 bar 上,会提示 let foo: string

类型推论

Type Inference

foo 的类型没有显示指定,TypeScript 会根据上下文自行推断。
let foo = 'TS';let foo: string = TS; 是等价的。

2 基础类型

Primitive Type

  • 支持 booleannumberstringsymbolundefinednull 基础类型
  • 新增 voidnever 基础类型
  • 新增 any 类型

JS 基础类型

TypeScript 支持 JavaScript 的基础类型

let tsBoo: boolean = false;
let tsNum: number = 0x10;
let tsStr: string = 'ts';
let tsSym: symbol = Symbol('ts');
let tsUnInit: undefined;
let tsEmpty: null = null;
TS 还支持基本包装类型 BooleanNumberStringSymbol,基本类型为基本包装类型的子类型。
// 基本包装类型 Boolean
let tsBool1: Boolean = new Boolean();
// 基本类型为基本包装类型的子类型
let tsBool2: Boolean = false;

新增基础类型

void

  • void 标识函数没有返回值(返回 undefined)。
function tsVoid(): void {
    // 没有 return,即 `return undefined` 时使用
}

void VS. undefined

  • 在 JS 中,void 为操作符,总返回 undefined; 而 undefined 在宽松模式下,可作变量。
  • 在 TS 中,void 作为返回值类型时,可用其他类型替换,而 undefined 不行。
function bar(callback: () => void) {}
function baz(callback: () => undefined) {}
// foo 返回 number 类型
function foo(): number { return 1; }

bar(foo); // foo 返回的 number 类型替换为 void 类型
baz(foo); // Error:`Type 'number' is not assignable to type 'undefined'.(2345)`)

never

  • never 标识函数不会 return。如抛出异常或生成器函数存在 while(true){}
  • never 是所有类型的子类型,可赋给任意类型。
function tsNever1(): never {
    throw new Error('Throw Exception or never return');
}
function *tsNever2(): never {
    while(true) {
        // ...
    }
}

基础类型兼容

never

前面说过,never 是所有类型的子类型。在 tsconfig.json 中:

  • strictNullChecks 为 false 时,可直接赋给任意类型。
  • strictNullChecks 为 true 时,never 需在赋值后才能使用。
let tsNever: never;
let tsNum: number;
let f = function():never {throw 'never'};

tsNum = tsNever; // `strictNullChecks` 为 true 时,提示 Error。
tsNever = f();
tsNum = tsNever;

any

TS 还增加了 any 类型,当不希望 TS 检查时使用。

  • 任意类型赋值给 any 类型或 any 类型赋值给任意类型 (never 除外) 均不会报错。

any

let tsAny: any = 'any value';
let tsNum: number = tsAny; // 可赋值给任意类型
tsAny = true; // 可被赋值任意类型

undefined && null

undefinednull 为子类型。在 tsconfig.json 中:

  • strictNullChecks 为 false 时,undefined、null 可赋值给除never 外的任意类型的变量。
  • strictNullChecks 为 true 时,undefined 只能赋值给 voidany 类型的变量。
let tsNum: number = undefined;
let tsVoid: void = undefined;

3 引用类型

Reference Type

  • 支持 Object、Array、Date、RegExp、Error、Function、Class 等类型
  • 新增 Tuple、Enum 类型

Object

object 描述(只读)对象类型

let tsObj1: object = { a: 1 };
tsObj1.x = 2; // Error: Property 'x' does not exist on type 'object'.

Array

三种定义方式(后两种详见下篇):

  1. _类型后加 []_,即 T[]
  2. Array Generic 数组泛型Array ReadonlyArray
  3. Number Index Signature 数值索引签名 : 通过 interface 定义类型
let tsArr1: string[] = ['foo'];

// 数组范型
let tsArr2: Array = ['foo'];
let readonlyArr: Array = ['foo']; // 只读数组

// 数值索引签名
interface IdxType { [index: number]: string } // type IdxType = string[];
let tsArr3: IdxType = ['foo'];

Tuple

元组:已知元素数量和类型的数组
let tsTuple: [string, number] ;

tsTuple = ['foo', 1];
tsTuple = [1, 'foo']; // Error

tsTuple[0].toUpperCase();
tsTuple[1].toUpperCase(); // Error

// 访问越界元素时会使用联合类型: (string | number)
tsTuple[2] = 'bar';
tsTuple[2] = 2;
tsTuple[2] = false; // Error

Enum

枚举: 定义一组命名常量(枚举成员只读)
  1. Numeric enums 数值枚举 : 可定义初始值(默认为 0),后面根据初始值递增。
  2. String enums 字符串枚举
  3. Heterogeneous enums 异构枚举
// Numeric enums
enum Color { Red = 2, Green, Blue };
/* 编译器反向映射为
var Color;
(function(Color) {
  Color[(Color["Red"] = 2)] = "Red";
  Color[(Color["Green"] = 3)] = "Green";
  Color[(Color["Blue"] = 4)] = "Blue";
})(Color || (Color = {}));
*/
let num: Color = Color.Green; // 3
let str: string = Color[3]; // Green

// String enums
enum Response { No = 'NO', Yes = 'YES' }

// Heterogeneous enums
enum HeterogeneousEnum { No = 0, Yes = "YES" }

Date RegExp Error

let date: Date = new Date();
let reg: RegExp = /\.ts$/;
let err: Error = new Error('error');

Function

描述参数和返回值类型

  • (paramter: T): U 描述函数定义
  • : (paramter: T) => U 描述函数变量
// 函数声明
function fn1(s: string): string {
    return s;
}
// 箭头函数表达式
let fn2 = (s: string): string => s;

// 函数变量 fn
let fn3: (str: string) => string = fn2;

参数

  • optional parameters 可选参数 : foo?: T
  • default parameters 默认参数 : foo: T = value
  • rest parameter 剩余参数 : ...rest: T[]
let fn2 = (
    s: string, // 必选参数
    b: string = '', // 默认参数
    c?: string, // 可选参数;位于必选参数后面
    ...d: string[] // 剩余参数;位于参数最后
): string => s;

重载

// Overload
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

Class

TS 保留并增添了功能 (目前 TS 与 ES 的类表现不一致)

ES :

class F {
    constructor(msg) {
        this.foo = msg;
    }
    getFoo() {
        return this.foo;
    }
}

class B extends F {
    constructor(msg) {
        super(msg);
    }
    getFoo() {
        return 'b' + super.getFoo();
    }
}

TS :

class F {
    foo: string
    constructor(msg: string) {
        this.foo = msg;
    }
    getFoo() {
        return this.foo;
    }
}

class B extends F {
    constructor(msg: string) {
        super(msg);
    }
    getFoo() {
        return 'b' + super.getFoo();
    }
}

结语
本篇介绍了 TS 的内置类型,下一篇介绍如何自定义类型。

CC BY-NC-ND 4.0

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

你可能感兴趣的:(typescript,ecmascript)