typescript学习小记

Tips

可选参数

?:

1
2
3
4
5
6
7
interface Person {
gender?: string; // 可选属性
}

function sayHello(person: string, age?: number): string {
return `Hello, ${person}. I am ${age}`;
}

报错

类型“Readonly<{}> & Readonly<{ children?: ReactNode; }>”上不存在属性“history”。ts(2339)

ts直接引用路由会报如上的错

1
const { history: { location: { pathname } } } = this.props;

引用下 RouteComponentProps 即可

1
2
3
4
5
6
7
8
import { RouteComponentProps } from 'react-router-dom';

export default class Home extends Component<RouteComponentProps> {
render() {
const { history: { location: { pathname } } } = this.props;
return <div className={style.test}>这是{pathname}</div>;
}
}

找不到模块“./index.module.less”。ts(2307)

global.d.ts 里声明:

1
2
3
4
declare module '*.module.less' {
const classes: { readonly [key: string]: string };
export default classes;
}

注意:函数的可选参数必须放在必需后

基本类型

空值 void

声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null:
let unusable: void = undefined;

Null 和 Undefined

在 TypeScript 中,可以使用 null 和 undefined 来定义这两个原始数据类型:

1
2
let u: undefined = undefined;
let n: null = null;

与 void 的区别是,undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量:

1
2
// 这样不会报错
let num: number = undefined;

联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种。

联合类型使用 | 分隔每个类型。

1
2
3
4

let num: number | string;
num = 6;
num = 'six';

函数重载

1
2
3
4
5
6
7
8
9
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('');
}
}

上例中,我们重复定义了多次函数 reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。

注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

类型断言

  • 联合类型可以被断言为其中一个类型
  • 父类可以被断言为子类
  • 任何类型都可以被断言为 any
  • any 可以被断言为任何类型

声明文件

全局变量的声明文件主要有以下几种语法:

  • declare var 声明全局变量
  • declare function 声明全局方法
  • declare class 声明全局类
  • declare enum 声明全局枚举类型
  • declare namespace 声明(含有子属性的)全局对象
  • interface 和 type 声明全局类型

npm 包

发布到 @types 里。我们只需要尝试安装一下对应的 @types 包就知道是否存在该声明文件,安装命令是 npm install @types/foo --save-dev。这种模式一般是由于 npm 包的维护者没有提供声明文件,所以只能由其他人将声明文件发布到 @types 里了。

类型别名

类型别名用来给一个类型起个新名字。使用type

1
2
3
4
5
6
7
8
type stringOrNumber = string | Function;
function getName(n: stringOrNumber): stringOrNumber {
if (typeof n === 'string') {
return n;
} else {
return n();
}
}

字符串字面量类型

字符串字面量类型用来约束取值只能是某几个字符串中的一个。

1
2
3
4
5
6
7
8
9
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
// do something
}

handleEvent(document.getElementById('hello'), 'scroll'); // 没问题
handleEvent(document.getElementById('world'), 'dbclick'); // 报错,event 不能为 'dbclick'

// index.ts(7,47): error TS2345: Argument of type '"dbclick"' is not assignable to parameter of type 'EventNames'.

枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景

枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

1
2
3
4
5
6
7
8
9
10
11
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true

console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true

事实上,上面的例子会被编译为:

1
2
3
4
5
6
7
8
9
10
var Days;
(function (Days) {
Days[Days["Sun"] = 0] = "Sun";
Days[Days["Mon"] = 1] = "Mon";
Days[Days["Tue"] = 2] = "Tue";
Days[Days["Wed"] = 3] = "Wed";
Days[Days["Thu"] = 4] = "Thu";
Days[Days["Fri"] = 5] = "Fri";
Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

枚举项只能被赋值为常数

类实现接口

实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。这个特性大大提高了面向对象的灵活性。

举例来说,门是一个类,防盗门是门的子类。如果防盗门有一个报警器的功能,我们可以简单的给防盗门添加一个报警方法。这时候如果有另一个类,车,也有报警器的功能,就可以考虑把报警器提取出来,作为一个接口,防盗门和车都去实现它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Alarm {
alert(): void;
}

class Door {
}

class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert');
}
}

class Car implements Alarm {
alert() {
console.log('Car alert');
}
}

泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

1
2
3
4
5
6
7
8
9
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}

createArray<string>(3, 'x'); // ['x', 'x', 'x']

上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。

资料: https://ts.xcatliu.com/

Copyright © 2017 - 2020 Timbok's Blog All Rights Reserved.

访客数 : | 访问量 :