簡體   English   中英

TypeScript:從 Enum 輸入接口,可選但至少 1

[英]TypeScript: Key in interface from Enum, Optional but at least 1

我想要一個 object 的接口,它有一個userId 或一個 customerId 要么一個,一個。

密鑰應該由枚舉定義(因此命名始終相同)。

我用這種方式,從另一個例子:

export enum EId {
  userId = 'userId',
  customerId = 'customerId',
}

export type IIdParam = {
  [key in EId]: string;
};

export interface IIdParamString extends IIdParam {
  paramString: string;
}

最后我想要這個 object:

  const params: IIdParamString = {
    userId: String('1234'),
    paramString: 'limit',
  };

但我得到一個錯誤:當[key in EId]不是可選的時,它會抱怨它需要 userId 和 customerId,如果不是可選的,則兩者都不是......

也許這不是我想要的正確方法。 我想枚舉中的值實際上不需要密鑰,但我無法從示例中更好地抽象它。

考慮這個例子:


export enum EId {
    userId = 'userId',
    customerId = 'customerId',
}

type AtLeastOne<Obj, Keys = keyof Obj> = Keys extends keyof Obj ? Record<Keys, string> : never

// credits goes to https://stackoverflow.com/questions/65805600/type-union-not-checking-for-excess-properties#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
    T extends any
    ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

export type IIdParamString =
    & StrictUnion<AtLeastOne<typeof EId>>
    & {
        paramString: string;
    }

/**
 * Ok
 */
const params: IIdParamString = {
    userId: '1234',
    paramString: 'limit',
};

/**
 * Expected errors
 */
const params2: IIdParamString = {
    paramString: 'limit',
};
const params3: IIdParamString = {
    userId: '1234',
    customerId: 'sdf',
    paramString: 'limit',
};

AtLeastOne - 你可以在這里找到完整的解釋

StrictUnion - 你可以在這里找到完整的解釋。 這個實用程序與你所做的never有相似的技巧。

我的方法對我的問題大體上是傳統的,以確保它是這個或那個

是的,你的方法沒問題。 但我建議你使用有區別的工會。 它們也稱為tagged unions 例如,參見F# 受歧視的工會 您可能已經注意到,每個聯合都有自己的標簽/標志/標記。 它有助於編譯器區分它們。

它可以是一個接口嗎? 很不幸的是,不行。 它可能只是類型,因為interface只能擴展靜態已知類型。 參見示例:

// An interface can only extend an object type or intersection of object types with statically known members.
export interface IIdParamString extends StrictUnion<AtLeastOne<typeof EId>> { // error
    paramString: string;
}

關於你最后一個問題,我不確定我是否理解。 您可以更新您的問題或(更好的)選項以單獨提問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM