TypeScript 是 JavaScript 的类型的超集,支持 ES6语法,支持面向对象编程的概念,如类、接口、继承、泛型等。在编译阶段需要编译器编译成 JavaScript 来运行。
TypeScript 的数据类型主要有如下:
有两种写法:
let arr:string[] = ['12', '23'];
let arr:Array = [1, 2];
动态类型(禁用类型检查),允许被赋值为任意类型
方法返回值的类型,表示该方法没有返回值
function hello(): void {
alert("Hello Runoob");
}
表示永远不会发生的值(如抛出错误或无限循环)
function error(message: string): never {
throw new Error(message);
}
类型安全的 any,使用前需显式类型检查
let userInput: unknown = "Hello";
if (typeof userInput === "string") {
let str: string = userInput; // 合法
}
固定长度和类型的数组
let user: [string, number] = ["Alice", 30];
数字枚举,默认从0开始自增
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
字符串枚举
enum LogLevel {
Error = "ERROR",
Warn = "WARN",
Info = "INFO"
}
通过 & 将多个类型合并为一个类型,包含了所需的所有类型的特性,本质上是一种并的操作
function extend(first: T, second: U) : T & U {
let result: = {}
for (let key in first) {
result[key] = first[key]
}
for (let key in second) {
if(!result.hasOwnProperty(key)) {
result[key] = second[key]
}
}
return result
}
通过 | 将多个类型合并为一个类型,类型为连接的多个类型中的任意一个,本质上是一个交的关系
function formatCommandline(command: string[] | string) {
let line = '';
if (typeof command === 'string') {
line = command.trim();
} else {
line = command.join(' ').trim();
}
}
类型别名用来给一个类型起个新名字,用type创建,常用于联合类型。
type Message = string | string[];
let greet = (message: Message) => {
// ...
};
1)可选属性:该属性可以不存在。可选属性要放在普通属性的后面,不然会导致编译错误。
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'Tom'
};
let tom: Person = {
name: 'Tom',
age: 25
};
2)任意属性:希望一个接口允许有任意的属性,使用索引签名的形式来满足。需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集。一个接口中只能定义一个任意属性。如果接口中有多个类型的属性,则可以在任意属性中使用联合类型。
// 报错
interface Person {
name: string;
age?: number;
[propName: string]: string;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
};
// 正确
interface Person {
name: string;
age?: number;
[propName: string]: string | number;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
};
3)只读属性:对象中的一些字段只能在创建的时候被赋值,用 readonly 定义只读属性
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
// 正确
let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};
// 报错
tom.id = 9527;
1)基本语法
// 接口
interface Point {
x: number;
y: number;
}
// 类型别名
type Point = {
x: number;
y: number;
};
2)表达更多种类的类型(类型别名独有):类型别名可以用于一些其他类型,比如联合类型和元组等。
// 联合类型
type ID = number | string;
// 元组类型
type Point = [number, number];
// 映射类型
type Readonly = {
readonly [P in keyof T]: T[P];
};
// 条件类型
type IsNumber = T extends number ? true : false;
3)声明合并(接口独有特性)。接口可以定义多次,会被自动合并为单个接口。
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
// 自动合并为:
interface Window {
title: string;
ts: TypeScriptAPI;
}
4)扩展/继承方式。接口和类型别名都能够被扩展,但语法有所不同(接口extends、类型别名&)。接口可以扩展类型别名,而反过来是不行的。
// 接口扩展
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
// 类型别名扩展
type Animal = {
name: string;
};
type Bear = Animal & {
honey: boolean
};
5)类实现implements。类可以以相同的方式实现接口或类型别名,但类不能实现使用类型别名定义的联合类型。
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
}
类型断言语法:值 as 类型 或 <类型>值,在 tsx 语法中必须使用前者
类型守卫:in关键字、typeof关键字、instanceof关键字、自定义的类型保护
(in 操作符可以安全的检查一个对象上是否存在一个属性)
function identity (value: T, message: U) : T {
console.log(message);
return value;
}
console.log(identity(68, "Semlinker"));
相关的基础知识:
1、typeof 操作符可以用来获取一个变量声明或对象的类型
2、keyof用于获取某种类型的所有键,其返回类型是联合类型。
3、in 用来遍历枚举类型
4、extends 关键字添加泛型约束
TypeScript 内置实用类型:
Partial 的作用就是将某个类型里的属性全部变为可选项 ?
Pick
Omit
参考:一份不可多得的 TS 学习指南、深入理解 TypeScript