[英]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.