繁体   English   中英

为什么我的接口无法扩展 typescript 中的联合类型

[英]Why does my interface fail to extend a union type in typescript

我有一个类型是两个接口的联合:

interface Foo {
  a: string
}
interface Bar {
  b: string
}
type Baz = Foo | Bar;

我想扩展它,但它给了我一个错误:

interface Qux extends Baz { // error!
  // ---------------> ~~~
  // An interface can only extend an object type or 
  // intersection of object types with statically known members.
  c: string;
}

interface Qux extends Baz { // error!
  c: string;
}

为什么我会收到该错误,我该怎么办?


具有更多上下文的问题的原始版本:

我编写了一个类型文件来扩充 npm 库中的Palette类型定义文件。 (具体的材料用户界面)。 如果我尝试让ODPaletteColorOptions扩展PaletteColorOptions ,如下面的代码所示,这不会成功扩展 PaletteColorOptions 接口。 结果如下:显然,ODPaletteColorOptions 接口只有附加键: 在此处输入图像描述

createPalette.d.ts
------------------
import { Palette as MuiPalette, PaletteColorOptions } from "@mui/material/styles/createPalette";

declare module "@mui/material/styles/createPalette" {

    export interface ODPaletteColorOptions extends PaletteColorOptions {
        1000: string,
        white: string,
        black: string,
        0: string,
        Search: string
    }

    export interface Palette extends MuiPalette{
        neutrals: ODPaletteColorOptions,
    };
}

这是现有 MUI 类型定义文件中对PaletteColorOptions的定义。

export type PaletteColorOptions = SimplePaletteColorOptions | ColorPartial;

在哪里

export interface SimplePaletteColorOptions {
  light?: string;
  main: string;
  dark?: string;
  contrastText?: string;
}
export type ColorPartial = Partial<Color>;
export interface Color {
  50: string;
  100: string;
  200: string;
  300: string;
  400: string;
  500: string;
  600: string;
  700: string;
  800: string;
  900: string;
  A100: string;
  A200: string;
  A400: string;
  A700: string;
}

但是,如果我没有扩展 PaletteColorOptions,而是显式扩展 SimplePaletteColorOptions 和 ColorPartial,那么扩展就可以工作。

import { Palette as MuiPalette, SimplePaletteColorOptions, ColorPartial } from "@mui/material/styles/createPalette";

declare module "@mui/material/styles/createPalette" {

    export interface ODPaletteColorOptions extends SimplePaletteColorOptions, ColorPartial {
        1000: string,
        white: string,
        black: string,
        0: string,
        Search: string
    }

    export interface Palette extends MuiPalette{
        neutrals: ODPaletteColorOptions,        
    };
}

为什么第一种方法会失败?

为了让编译器处理interface类型(以及class类型的实例,可以看作具有与类同名的interface ),它们需要有一组静态已知键 联合类型有多组键,因此您不能将它们扩展为接口。 有关可以扩展哪些类型的事物(例如,object 类型和此类类型的交集)以及一些不能扩展的事物(例如,泛型类型参数)的描述,请参见microsoft/TypeScript#13604

这就是为什么您可以单独扩展FooBar ,但不能扩展联合Foo | Bar Foo | Bar


幸运的是,您可以使用交集类型获得几乎相同的效果,如TS 手册文档中所述,类型别名和接口之间的差异

type Qux = Baz & { c: string }; // okay

现在, Qux的行为就像Baz具有string值的c属性,这大概是您想看到的:

function processQux(q: Qux) {
  console.log(("a" in q ? q.a : q.b).toUpperCase() + " " + q.c);
}

const q: Qux = { a: "hey", c: "you" } // okay
processQux(q) // HEY you
processQux({ b: "it's", c: "me" }) // IT'S me
processQux({ c: "oops" }) // error! 
// Argument of type '{ c: string; }' is not assignable to parameter of type 'Qux'.
  

Playground 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM