TypeScript CheetSheat

2,739 阅读5分钟

TypeScript 风靡全球后不懂 TypeScript 的前端绝对不是一个好前端。TypeScript 的设计来源于大多数的静态语言,如果曾经有静态语言的开发经验,TypeScript 一整个下午就能上手。

这里记录一下 TypeScript 常用的一些语法层面的东西,方便日后查阅。

Get Start

mkdir ts-learn
npm install @types/node
npm install -g ts-node
npm install -g typescript

Tips: 为压缩页面长度 + 在 ts-node 中比较方便的执行,所有代码尽量写在了同一行。

1. Type

booleannumberstringvoidundefinednull

const a: number = 3;

const b: number = undefined;

funtion Foo(): void {}

Tips: undefined 和 null 是所有类型的子类型。即 undefined、null 类型的变量都可以赋值其他类型。void 不可以!

2. Any

let a: any = 1;
a = 'a'

Tips: 干啥都可以,等同于 ES 时代的 JS,对他操作之后返回的也是 any。可以访问变量里面的任何属性或方法

3. Type Inference

> let y = 1;
undefined
> y = 'a'
⨯ Unable to compile TypeScript
[eval].ts (1,1): Type '"a"' is not assignable to type 'number'. (2322)

> let l = null
undefined
> l = 1
1

Tips: 在没有明确类型的时候会推到出一个类型。推到不出的时候认为是 any(如: undefined, null 这种)

4. Union Types

> let p: number | string = 1;
undefined
> p = 2
2
> p = true
⨯ Unable to compile TypeScript
[eval].ts (1,1): Type 'true' is not assignable to type 'string | number'. (2322)
> p = '2'
'2'


> let j: number | string
undefined
> j.length
⨯ Unable to compile TypeScript
[eval].ts (1,3): Property 'length' does not exist on type 'string | number'.
  Property 'length' does not exist on type 'number'. (2339)
> j = '1'
'1'
> j.length
1

Tips: 在推导(Type Inference)出到底是哪个 Type 之前,访问变量的属性或方法的时候有限制,只能访问共有的属性或方法

5. Interfaces

> interface Foo { a: number, b: string, c?: boolean}
undefined
> let BBar: Foo = { a: 1, b: 2 }
⨯ Unable to compile TypeScript
[eval].ts (1,5): Type '{ a: number; b: number; }' is not assignable to type 'Foo'.
  Types of property 'b' are incompatible.
    Type 'number' is not assignable to type 'string'. (2322)

> interface Foo { readonly a: number, b: string, c?: boolean, [propName: string]: any}

Tips:

表示该属性可以不存在。但总的来说都不允许添加未定义的属性。

[propName: string]: any 表示 Foo 中可以有 key 是 string, value 是 any 的任意属性,值的注意的是这里的 stringany 必须覆盖到之前定义的确定属性和可选属性

readonly 表示该属性只读,指第一次给对象赋值的时候而不是第一次给只读属性赋值的时候

接口可以是对对象 Shape 的描述,也可以是对行为的抽象(函数输入返回(见 Fuction)或者类的抽象(见class))。

6. Array

> let g: (number|string)[] = [1, 2, 3, '4']
undefined

> let h: Array<number> = [1, 2, 3]
undefined

> let kk: any[] = [1, '1', true]

Tips: 泛型会经常被使用;Array Like Object 不是数组

7. Function

> function a(a: number, b: string, c: string = 'c', d?: string): string { return '1'}

> let r = function (a: number, b: string, c: string = 'c', d?: string): string { return '1' }
 
> let r: (a: number, b: string, c: string, d?: string) => string = function (a: number, b: string, c: string = 'c', d?: string): string { return '1' }

> interface R { (a: number, b: string, c: string, d?: string): string }
> let r: R = function (a: number, b: string, c: string = 'c', d?: string): string { return '1' }

> function g(a: number[], ...other: any[]): void { }

> function g(a: number): number;
> function g(a: string): string;
> function g(a: number|string) : number|string {}
> 
> interface R {
    (a: number, b: string, c: string, d?: string): string;
    reset(): void;
    num: number
 }
> let r: R = function (a: number, b: string, c: string = 'c', d?: string): string { 
    let tep = <R>function(l: number) {}; // <R> 的写法参见 Type Assertion
    tep.reset() = function() {}
    tep.num = 888;
    return tep;
  }

Tips:

可选参数必须放在最后。

2 和 3 是函数表达式。2 中的 r 是 Type Inference 出来的,要强制的话需要写成 3。=> 表示函数的定义,左侧是输入类型,右侧是输出类型。

4 是用接口定义的,更加清晰,同时 Interface 除了定义输入返回之外还可以定义函数里面的方法或者属性。(承 5.interfaces)

6 重载,更加清晰的明确对应关系

8. Type Assertion

function g(a: number|string): void {
    if(<string>a.length>0) {
        console.log('isString');
    } else {
        console.log('is not string');
    }
}

Tips: 只能断言预估好的之一,不能胡乱断

9. Declare

// zepto.d.ts
declare const $: (string) => any;

// index.ts
/// <reference path="./zepto.d.ts" />
$('#a');

Tips: 第三方库的 Types 一般使用 tnpm install @types/xx。参考 types

10. Standard built-in objects

> let hh: Date = new Date()
undefined
> hh
2017-11-15T16:43:24.128Z

Tips: 定义文件 参见这里。包含 ES、DOM、BOM 等,Node 使用需要安装相应的 types。

11. Type Alias

type a = (a?: string) => string
function g(m: string|a): void {}

12. String Literal Types

type specialType = 'a' | 'b' | 'c';
let a: specialType = 'a'

13. Tuple

let a: [number, string] = [1, '2']

Tips: 越界只能是已知类型的联合类型;可单独修改某个一个值;

14. Enum

enum days = { a, b, c }

enum days = { a = 1.5, b, c }

15. Class

class A extends B {
    public name: string;
    private age: number;
    protected grade: string;
    constructor(name) {
        super(props);
    }
}

abstract class Foo {
    public name: string;
    constructor(name) {
        this.name = name;
    }
    public abstract say()
}
class Bar extends Foo {
    public say() {
    
    }
}
let bar: Bar = new Bar()


interface M {
    public method1()
}
interface N {
    public method2()
}
interface L extends N {
    public method3();
}
class Bar extends Foo implements M, L {
    public method1() {};
    public method2() {};
    public method3() {}
}

Tips:

public、private、protected 和 Java 中行为一致。

Abstract Class 不能被实例化,只能被其他的 class 继承,同时 abstract 中定义的 abstract 方法必须要被继承的子类实现(implements)。

Interfaces 用于不同 class 之间共有的属性或者方法。 一个 class 可以 implements 多个 interface,interface 之间也可以继承 (承上 5.interfaces)

16. Generics

function methods<T>(a: number, b: T): Array<T> {}

function swapTurple<T><U>(turple: [T, U]): [U, T] {}

interface LengthGen {
    length: number
}
function testMethod<T extends LengthGen>(a: T): T {}

function testMethod<T extends U>(a: T, b: U): T {} // 保证 T的属性 U 上一定也会有

interface FooInterface<T> {
    (a: number, value: T): Array<T>
}
let foo: FooInterface<any> = function method<T>(a: number, value T): Array<T> {}

Tips:

为了让类型更加准确,不全是 any

泛型也可以继承,以保证泛型中一定有某些属性或者方法(泛型约束)

泛型接口

参考资料