簡體   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