Typescipt 入门教程之类型系统详解
类型注解
- 基本类型注解
let a: number;
let b: string;
let bool: boolean;
a = '123' // 错误
b = 123 // 错误
c = 'false' // 错误
- 数组注解
let aArray: number[]
let bArray: string[]
let cArray: boolean[]
aArray = ['1'] // 错误
bArray = [1] // 错误
cArray = ['false'] // 错误
- 接口注解
接口是 Typescript 的一个核心知识,它能将多个类型注解合并成一个类型注解
interface Animal {
name: string,
eat: string,
fly: boolean
}
let animal: Animal
animal = {
name: 'cat',
eat: 'fish',
fly: 'false' // 错误
}
- 内联类型注解
let animal: {
name: string,
eat: string,
fly: boolean
}
animal = {
name: 'cat',
eat: 'fish',
fly: 'false' // 错误
}
- 特殊类型
除了基本类型外,Typescript还有一些特殊的类型,它们是 any、null、undefined、void
any 兼容所有的类型,能与任何类型赋值
null 和 undefined 是所有类型的子类型,和被标注为 any 的变量一亲,都能被赋值任意类型的变量
void 用来表示一个函数没有返回值
// any
let a: any;
a = 1
a = '1'
a = false
// null undefined
let b: number
let c: string
let d: boolean
b = null
c = undefined
d = null
// void
function log(msg: string): void {
console.log(msg)
return '1' // 错误
}
- 泛型
function reverse<T>(items: T[]): T[] {
const result = []
for (let i = items.length -1; i >=0; i--) {
result.push(items[i])
}
return result
}
const a = [1, 2, 3]
console.log(reverse(a))
const b = ['1', '2', '3']
console.log(reverse(b))
- 元组
let a: [number, string, boolean]
a = [1, '1', true]
a = ['1', 1, 'false'] // 错误
- 类型别名
type A = number | string | boolean
let a: A
a = 1
a = '1'
a = true
type B = string | { text: string }
let b:B
b = '1'
b = {
text: '1'
}
type C = [number, string, boolean]
let c:C
c = [1, '1', true]
type Callback = (name: string) => void
- 类型断言
迁移老代码,需要兼容 Javascript 代码,可以使用类型断言来减少错误
let a = 123
let b = 'hey'
a = b as any
- 第三方npm模块
与全局变量的声明相似,可以快速定义一个全局模块。
declare module 'jquery'
- 额外的非 Javascript 资源
declare module '*.css';
declare module '*.html';
- @types
大多数常用的第三方模块,社区基本都有现成的 Typescript 声明,可以通过 npm 来安装和使用 @types,如 Jquery 添加声明文件
npm install @types/jquery --save-dev
控制全局,对于某些团队而言,拥有允许全局泄露的定义可能是一个问题,可以通过配置 tsconfig.js 的 compilerOptions.types 选项,引入有意义的类型。
{
"compilerOptions": {
"types": [
"jquery"
]
}
}
- 接口
声明变量尽量用接口,方便扩展。 Typescript 接口是开放式的。
// 示例1
declare const myPoint: { x: number, y: number }
// 示例2
interface Point {
x: number;
y: number;
}
declare const myPoint: Point;
// d.ts 库
interface Point {
z: number
}
let myPoint.z // 允许
类实现接口
interface Point {
x: number;
y: number;
}
// 类实现接口
class MyPoint implements Point {
constructor(public x: number, public y: number) {}
// x: number;
// y: number;
// 两种都可以,缩写
}
- 枚举
enum AnimalFlags {
None = 0,
HasClaws = 1,
CanFly = 2
}
interface Animal {
flags: AnimalFlags,
[key: string]: any
}
function printAnimalAbilities(animal: Animal) {
const animalFlags = animal.flags;
if (animalFlags & AnimalFlags.HasClaws) {
console.log('animal has claws');
}
if (animalFlags & AnimalFlags.CanFly) {
console.log('animal can fly');
}
if (animalFlags === AnimalFlags.None) {
console.log('nothing');
}
}
let animal = { flags: AnimalFlags.None };
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws;
printAnimalAbilities(animal); // animal has claws
animal.flags &= ~AnimalFlags.HasClaws;
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly;
printAnimalAbilities(animal); // animal has claws | animal can fly
组合标记,用来在枚举类型中定义方便快捷的方式,
使用 |= 来添加一个标记;
组合使用 &= 和 ~ 来清理一个标记
使用 | 来合并标记
- 函数重载
Typescript 允许声明函数重载。
function margin(all: number);
function margin(top: number, right: number);
function margin(top: number, right: number, bottom: number, left: number);
function margin(top: number, right?: number, bottom?: number, left?: number) {
if (right === undefined && bottom === undefined && left === undefined) {
right = bottom = left = top
} else if (bottom === undefined && left === undefined) {
bottom = top;
left = right;
}
return {
top,
right,
bottom,
left
}
}
margin(1);
margin(1, 1);
margin(1, 1, 1); // 错误 没有需要 3 参数的重载,但存在需要 2 或 4 参数的重载
margin(1, 1, 1, 1);