TS知识点总结
文章目录
一、ts中可选类型没有相关属性的问题
在项目中,有时候会遇到后端下发可选属性如:
在使用该类型的实例时如:
当 arr可能为undefined时,不能参与比较
arr?.length > 0 // 会报错
if (arr?.length) // 不会报错
二、interface与type的区别
相同点
两者都可以进行扩展,只是语法不同
interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
type
type Name = {
name: string;
}
type User = Name & { age: number };
interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}
不同点
type 可以而 interface 不行
1.type
可以定义类型的别名,联合元素,元组类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
2.type
可以使用typeof
获得的实例类型进行赋值
// 当你想获取一个变量的类型时,使用 typeof
let div = document.createElement('div');
type B = typeof div
3.特殊操作
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
interface 可以而 type 不行
1.interface
能够声明合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
2.interface
可以被实现(implements
)
interface SpecialClass {
age: number;
}
class SP implements SpecialClass {
age: number;
constructor(age: number) {
this.age = age;
}
}
三、TS的协变与逆变
维基百科的定义:
协变与逆变(covariance and contravariance)是在计算机科学中,描述具有父/子型别关系的多个型别通过型别构造器、构造出的多个复杂型别之间是否有父/子型别关系的用语。
就是说原本具有父子关系的类型,在经过类型构造器后产生的类型是否还保持原本的父子关系。若是,称作协变;若父子关系颠倒,则称作逆变。
例子:
interface Animal {
age: number
}
interface Dog extends Animal {
bark(): void
}
协变
let animals: Animal[]
let dogs: Dog[]
animals = dogs
animals[0].age // ok
那么,对于 type MakeArray<T> = T[]
这个类型构造器来说,它就是 协变(Covariance) 的。
逆变
有这样两个函数类型:
let visitAnimal = (animal: Animal) => void;
let visitDog = (dog: Dog) => void;
若是这样的函数实现:
let visitAnimal = (animal: Animal) => {
animal.age
}
let visitDog = (dog: Dog) => {
dog.age
dog.bark()
}
若 visitAnimal = visitDog
,这里会发生错误。赋值后,visitAnimal
指向的是visitDog
的函数实现,所以在传入Animal
类型的参数后就会报错。
但是相反,若visitDog = visitAnimal
,visitDog
指向的是visitAnimal
的函数实现,在传入Dog
类型的参数后,并不会调用Dog
类型专有的属性或方法,因此不会报错。这里,父子关系就发生了翻转,因此我们称type MakeFunction<T> = (arg: T) => void
这种类型构造器就是逆变的。
参考文章:
[1]: https://juejin.cn/post/6855517117778198542
[2]: https://juejin.cn/post/6905666894984904717