谈谈 typescript 中的 interface

前言

Typescript 里的 Interface 的作用非常广泛,但我觉得最大的好处了有助于对参数的约束,还有另外一个好处就是在 vscode 里有非常好的智能提示功能。

下面就来谈谈 Typescript 中的 Interface,顺便说一点 Typescript 在 React 里的组件写法。

简单点

简单来说 interface 就是用来定义参数的接口,也可以对某些变量进行声明,指定变量的类型等作用。

1
2
3
4
5
6
7
8
9
interface IProps {
title: string,
}

const Button = ({ title }: IProps) => (
<Touch>
<Text>{title}</Text>
</Touch>
);

当然 interface 也不只如此,对于非必填的可以使用 ? 指定。

1
2
3
4
5
6
7
8
9
10
11
interface IProps {
title: string,

style?: ViewStyle,
}

const Button = ({ title, style }: IProps) => (
<Touch style={style}>
<Text>{title}</Text>
</Touch>
);

此外,还可以继承已有的,这样可以避免一些重复的编写。

1
2
3
4
5
6
7
8
9
10
11
interface IProps extends TouchableOpacityProps {
title: string,

style?: ViewStyle,
}

const Button = ({ title, style }: IProps) => (
<Touch style={style}>
<Text>{title}</Text>
</Touch>
);

这样就可以不用重新写 TouchableOpacity 的 Props 了,直接继承即可。

其他,如果组件的声明还有其他属性需要用到,可以使用多余的键名方式。

1
2
3
4
5
6
interface IProps extends TouchableOpacityProps {
title: string,
style?: ViewStyle,

[rest: string]: any,
}

这样就算是使用 <Button name='abc' /> 也不会报错。

如果 props 是一个函数,那怎么写呢?函数有普通的写法,以及箭头函数的方式。

1
2
3
4
5
6
7
8
interface IProps extends TouchableOpacityProps {
title: string,
style?: ViewStyle,
renderIcon?: (icon: string) => React.ReactElement<any>,
renderHeader?(): React.ReactElement<View>,

[rest: string]: any,
}

如果 Props 是一个函数,并且有回调函数时怎么写?同时也有多种写法。

1
2
3
4
5
6
7
8
9
10
interface Callback {
(item: any, index: number): any
}

interface IProps extends TouchableOpacityProps {

renderItem?: (item: any, index: number, cb: Function) => any,
renderItem2?: (item: any, index: number, cb: Callback) => any,
renderItem3?: (item: any, index: number, cb: (item: any, index: number) => any) => any,
}

这时可以直接写一个 Function,但是没有对应的参数提示,也可以写一个 interface 给回调函数,也可以直接在参数里写回调函数的类型(字面量接口)。

如果某个 Props 是一个枚举项时应该怎么写?使用 | 可以进行或操作。

1
2
3
interface IProps extends TouchableOpacityProps {
type?: 'primary' | 'danger' | 'dashed',
}

type 只能是这几个中的其中一个。也适用也多类型的写法:string | number

当 type 只有一个类型时那就是必须了。

1
2
3
4
5
interface IProps extends TouchableOpacityProps {
type?: 'primary',
}

<Button type='primary' />

因此,这样会很古怪,type 只能选择 primary。

很遗憾的是 interface 不能编写默认值。

如果 Props 支持很多的类型呢?这时可以使用交叉类型

交叉类型是将多个类型合并为一个类型。这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。

1
2
3
interface IProps extends TouchableOpacityProps {
data?: Person & Serializable & Loggable,
}

这个 data 就综合了 Person、Serializable、Loggable 的所有属性与方法。