前言
Typescript是前端离不开的一项技术了,作为初学者,学习起来又很费劲!官网文档又臭又长,狗都不看!网上教程一上来就是20小时,让人望而生怯!
对于Typescript,我们其实并不需要学的非常深入,简单了解简单使用就好了!因此,一篇节省时间,通俗易懂的教程很重要!
本文就要简单但高效的带你入门类型别名、泛型!
关联的上一篇文章: # TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
类型别名
在TypeScript中,类型别名(Type Aliases)允许你为一个类型创建一个新的名字。
基本类型别名
你可以为基本类型(如字符串、数字、布尔值等)创建别名:
在TypeScript中,类型别名(Type Aliases)允许你为一个类型创建一个新的名字。
type StringAlias = string;
type NumberAlias = number;
type BooleanAlias = boolean;
联合类型别名
类型别名可以用于联合类型,这样可以使代码更简洁:
type ID = number | string;
let userId: ID = 123;
userId = "abc123";
接口与类型别名的区别
实际上,在大多数的情况下使用接口类型和类型别名的效果等价,但是在某些特定的场景下这两者还是存在很大区别。
TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 而接口的作用就是为这些类型命名和为你的代码或第三方代码定义数据模型。
type(类型别名)会给一个类型起个新名字。 type 有时和 interface 很像,但是可以作用于原始值(基本类型),联合类型,元组以及其它任何你需要手写的类型。起别名不会新建一个类型 - 它创建了一个新 名字来引用那个类型。给基本类型起别名通常没什么用,尽管可以做为文档的一种形式使用。
Objects / Functions
两者都可以用来描述对象或函数的类型,但是语法不同。
interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}
type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;
其他类型别名
与接口不同,类型别名还可以用于其他类型,如基本类型(原始值)、联合类型、元组。
// primitive
type Name = string;
// object
type PartialPointX = {
x: number; };
type PartialPointY = {
y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
// dom
let div = document.createElement('div');
type B = typeof div;
接口可以定义多次,类型别名不可以
与类型别名不同,接口可以定义多次,会被自动合并为单个接口。
interface Point {
x: number; }
interface Point {
y: number; }
const point: Point = {
x: 1, y: 2 };
扩展
两者的扩展方式不同,但并不互斥。接口可以扩展类型别名,同理,类型别名也可以扩展接口。
接口的扩展就是继承,通过 extends 来实现。类型别名的扩展就是交叉类型,通过 & 来实现。
接口扩展接口
interface PointX {
x: number
}
interface Point extends PointX {
y: number
}
类型别名扩展类型别名
type PointX = {
x: number
}
type Point = PointX & {
y: number
}
接口扩展类型别名
type PointX = {
x: number
}
interface Point extends PointX {
y: number
}
类型别名扩展接口
interface PointX {
x: number
}
type Point = PointX & {
y: number
}
泛型
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。
引入
下面创建一个函数, 实现功能: 根据指定的数量 count 和数据 value , 创建一个包含 count 个 value 的数组 不用泛型的话,这个函数可能是下面这样:
function createArray(value: any, count: number): any[] {
const arr: any[] = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr1 = createArray(11, 3)
const arr2 = createArray('aa', 3)
console.log(arr1[0].toFixed(), arr2[0].function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())split(''))
这样写不会报错,但是toFixed() split('')方法都没有ts的语法提示
function createArray2 <T> (value: T, count: number) {
const arr: Array<T> = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr3 = createArray2<number>(11, 3)
console.log(arr3[0].toFixed())
// console.log(arr3[0].split('')) // error
const arr4 = createArray2<string>('aa', 3)
console.log(arr4[0].split(''))
// console.log(arr4[0].toFixed()) // error
这里的T相当于是一个形参
多个泛型参数的函数
一个函数可以定义多个泛型参数
function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())
泛型接口
在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型
interface CommonResponse<T> {
status: number;
errMsg: string;
ok: boolean;
data: T ;
}