TypeScript--接口(interface)

介绍

TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

const getFullName = ({ firstName, lastName}) =>{
    return `${firstName}${lastName}`
}

getFullName({
    firstName:'liu',
    lastName:123
})

如果你的代码报如下错误

TypeScript--接口(interface)

修改 tsconfig.json,将 strict 改为 false

TypeScript--接口(interface)

上面我们期望的两个参数都是字符串,但没有限制, lastName 传的是数值,也不会报错,如果我们要限制参数,可以使用 ts 里的接口

// 定义了一个接口,名称为 NameInfo,里面的两个参数类型都是 string 类型的
interface NameInfo {
    firstName: string,
    lastName: string,
}

// 指定对应的接口名称,就会使用里面对应的类型
const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
}

// 只能传对应类型的值
getFullName({
    firstName:'liu', 
    lastName:"zou"
})

可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。

// 定义了一个接口,名称为 NameInfo,里面的两个参数类型都是 string 类型的
interface NameInfo {
    firstName: string,
    lastName?: string,  //  lastName 后面加了 ? ,代表 lastName 参数是可选的
}

// 指定对应的接口名称,就会使用里面对应的类型
const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
}

// 只能传对应类型的值
getFullName({
    firstName:'liu', 
    // lastName:"zou" // 可选的,可以不需要传
})

带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个 符号。

只读属性

一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly 来指定只读属性

interface NameInfo {
    firstName: string,
    readonly lastName: string,  //  readonly ,代表这个参数只读,不能修改
}

const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
}

getFullName({
    firstName:'liu', 
    lastName:"zou"  // 第一次赋值时可以
})

额外的属性检查

interface NameInfo {
    firstName: string,
    lastName: string,  
}

const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
} 

getFullName({
    firstName:'liu', 
    lastName:"zou", 
    size: 2 // 多传了一个 size 参数,会报错
})

绕开这些检查非常简单。 最简便的方法是使用类型断言:

interface NameInfo {
    firstName: string,
    lastName: string,  
}

const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
} 

getFullName({
    firstName:'liu', 
    lastName:"zou", 
    size: 2  
} as NameInfo)  // 使用类型断言,多传了个参数就不会报错了

然而,最佳的方式是能够添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性

interface NameInfo {
    firstName: string,
    lastName: string,  
    [propName: string]: any;  // 字符串索引签名
}

const getFullName = ({ firstName, lastName}: NameInfo) =>{
    return `${firstName}${lastName}`
} 

getFullName({
    firstName:'liu', 
    lastName:"zou", 
    size: 2  
}) 

表示的是 NameInfo 可以有任意数量的属性,并且只要它们不是 firstName 和 lastName,那么就无所谓它们的类型是什么。

继承接口

和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里,可以更灵活地将接口分割到可重用的模块里

interface Shape {
    color: string;
}

// 继承接口使用  extends 关键字
interface Square extends Shape {  // Square 接口继承了 Shape 接口,则 Square 接口里就有 Shape 接口的属性 color了
    sideLength: number;
}

一个接口可以继承多个接口,创建出多个接口的合成接口。

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

const cart: Square = {  // 必须要下面的三个参数
    sideLength: 12,
    penWidth: 1,
    color:'red'
}