typescript不能使用接口扩展联合类型

3,902 阅读1分钟

今天想对react-transiton-group进行二次封装,发现了typescript中interface和type的区别之一,就是接口(interface)不能扩展(extends)联合类型。

报错

interface CTransitionProps extends CSSTransitionProps {
    animation?: AnimationName,
    wrapper?: boolean
}

TS2312: An interface can only extend an object type or intersection of object types with statically known members.

接口只能扩展对象类型或对象类型与静态已知成员的交集。

什么是联合类型?

我这里直接把typescript官方文档的例子拿过来用了

这个函数中形参padding的期待类型是`padding或者number

 function padLeft(value: string, padding: any) {
     if (typeof padding === "number") {
         return Array(padding + 1).join(" ") + value;
     }
     if (typeof padding === "string") {
         return padding + value;
     }
     throw new Error(`Expected string or number, got '${padding}'.`);
 }

但是把padding参数类型指定成了any,这就是说我们可以传入一个既不是 number也不是 string类型的参数。

 let indentedString = padLeft("Hello world", true); // 编译阶段通过,运行时报错

在传统的面向对象语言里,我们可能会将这两种类型抽象成有层级的类型。 这么做显然是非常清晰的,但同时也存在了过度设计。 padLeft原始版本的好处之一是允许我们传入原始类型。 这样做的话使用起来既简单又方便。 如果我们就是想使用已经存在的函数的话,这种新的方式就不适用了。

我们可以用联合类型代替any

 function padLeft(value: string, padding: string | number) {
     // ...
 }

联合类型表示一个值可以是几种类型之一。 我们用竖线( |)分隔每个类型,所以 number | string表示一个值可以是 number 或者 string

CSSTransitionProps

CSSTransitionProps就是一个联合类型

Snipaste_2022-02-17_09-43-35.png

Snipaste_2022-02-17_09-43-56.png

使用type

 type CTransitionProps = CSSTransitionProps & {
     animation?: AnimationName,
     wrapper?: boolean
 }