描述对象的数据类型:
- 使用class/constructor描述
- 用type或interface描述
使用class/constructor描述
const a: Date = ()=> console.log(1) // Error 会报错缺少日期的一些属性
const a: Function = ()=> console.log(1) // Ok
class Person {
name: string
constructor(name: string) {
this.name = name
}
speak() {
console.log(`${this.name} is speaking`)
}
}
const p1 = new Person('lin') // 新建实例
interface类型
interface(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。
定义 interface 一般首字母大写,代码如下:
interface Person {
name: string
age: number
}
const p1: Person = { name: 'lin', age: 18}
注意:属性必须和类型定义的时候完全一致,少写了属性,或多写属性都会报错(interface 不是 JS 中的关键字,所以 TS 编译成 JS 之后,这些 interface 是不会被转换过去的,都会被删除掉,interface 只是在 TS 中用来做静态检查)
可选属性:
跟函数的可选参数是类似的,在属性上加个 ?,这个属性就是可选的,比如下面的 age 属性
interface Person {
name: string
age?: number
}
const p1: Person = { name: 'lin' }
只读属性:
如果希望某个属性不被改变,可以使用readonly关键字
interface Person {
readonly id: number
name: string
age: number
}
let ikun:Person = {
id:o,
name:"坤坤",
age:12
}
ikun.id = 5 // Error 改变这个只读属性时会报错
duck typing(鸭子类型)
事实上,interface 还有一个响亮的名称:duck typing(鸭子类型)
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
-- James Whitcomb Riley
interface 的写法非常灵活,它不是教条主义。用 interface 可以创造一系列自定义的类型。只要数据满足了 interface 定义的类型,TS 就可以编译通过。
鸭子类型是一个与动态类型( dynamic typing )相关的概念,其中关注的是它定义的方法,而不太关注对象的类型或所属类。当您使用鸭子类型时,你无需做检查类型。相反,您要检查给定方法或属性是否存在
举个例子:
interface FunctionWithProps {
(x: number): number
name: string
}
FunctionWithProps 接口描述了一个函数类型,还向这个函数类型添加了 name 属性,这看上去完全是四不像,但是这个定义是完全可以工作的。
const fn: FunctionWithProps = (x) => { return x}
fn.name = '哈哈哈哈哈'
事实上, React 的 FunctionComponent(函数式组件) 就是这么写的
interface FunctionComponent<P = {}> { (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
FunctionComponent 是用 interface 描述的函数类型,且向这个函数类型添加了一大堆属性
自定义属性(可索引的类型):
有的时候,你不能提前知道一个类型里的所有属性的名字,但是你知道这些值的特征。
这种情况,你就可以用一个索引类型 (index signature) 来描述可能的值的类型
interface RandomKey {
[propName: string]: string
}
const obj: RandomKey = {
a: 'hello',
b: 'lin',
c: 'welcome',
}
属性继承:
对接口使用 extends关键字允许我们有效的从其他声明过的类型中拷贝成员,并且随意添加新成员 。
interface Person {
name: string
age: number
}
interface Student extends Person {
grade: number
}
//Student 继承了Person声明过的所有类型,并且随意添加新成员
const person:Student = { name: 'lin', grade: 100, age:98}
//接口也可以继承多个类型
interface Student extends Person ,Student{}
interface 和 class 的关系(implements ):
interface 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。interface 同样可以用来约束 class,要实现约束,需要用到 implements 关键字,implements 是实现的意思,class 实现 interface。
比如一个会干饭的人类
interface Persion {
eatRice(): void
}
class man implements Persion {
eatRice() {
console.log('干饭干饭')
}
//不写这个eatRice方法就会报错 定义了约束后,class 必须要满足接口上的所有条件
}
类也可以被多个接口约束
class KunSon implements A, B {
//。。。。
}
约束构造函数和静态属性:使用 implements 只能约束类实例上的属性和方法,要约束构造函数和静态属性,需要这么写
interface Persion {
new (age: number): void
height: number
}
const Man:CircleStatic = class Circle {
static height: 180
public son: number
public constructor(age: number) {
this.radius = radius
}
}
implements 语句仅仅检查类是否按照接口类型实现,但它并不会改变类的类型或者方法的类型。一个常见的错误就是以为 implements 语句会改变类的类型——然而实际上它并不会(只有约束class作用):
interface A {
x: number;
y?: number;
}
class C implements A {
x = 0;
}
const c = new C();
c.y = 10;
//如上面例子,以往我们鼠标放c上去会显示c的可选类型,但现在什么都没有
Type(类型别名)
类型别名(type aliase),听名字就很好理解,就是给类型起个别名。
type Name = string
const a:Name = 'ikun' // 还是字符串类型
tyep FalseLike = 0 | '' | null | undefined | false // 为false伪类型
type arrItem = number | string // 联合类型
type StudentAndTeacherList = [Student, Teacher] // 元组类型
Type定义对象类型:
type可以定义对象类型
type Person = {
name: Name
}
实现继承(交叉类型):
type Student = Person & {
grade: number
}
type和interface对比
他们俩是完全不同的概念,但网上喜欢拿来对比。。。。(就简单比一下)
- interface 是接口,相当于类型声明 ,只用来描述一个对象(可以重新赋值)
- type 只是别名 ,可以描述所有数据类型(不可重新赋值)
怎么选择用哪一个??
结论:
- 对外尽量使用 interface(方便扩展)
- 对内尽量用type 防止代码分散(保证类型的纯真性)
//对外API尽量使用 interface
interface X {
name:string
}
interface X {
age:number
}
const a:X ={
name:'ikun',
age:18
} // OK interface会将name和age合并 所以可扩展
type Y ={
age:number
}
type Y ={
name:string
} // Error 这时候报错 不能重复声明Y
参考资料:
类_TypeScript中文文档
https://zhuanlan.zhihu.com/p/489207162
TypeScript: Documentation - Advanced Types