[英]Destructure/access a property that may or may not exist on an object union type
[英]TypeScript type alias to pick values of an object matching a set of arbitratry keys that may or may not exist in the object
考慮以下:
type X = {foo: string};
type Y = {foo: number};
type Z = {foo: string, bar: number};
type W = {bar: string};
type Q = {baz: string};
type ValueOf<T, K> = ...
我想為任意字符串鍵的聯合創建ValueOf
類型 - 它可能是也可能不是目標 object 的一部分 - 匹配目標 object中與任何這些鍵相對應的任何值。
ValueOf<X, 'foo' | 'bar'> -> should give 'string'
ValueOf<Y, 'foo' | 'bar'> -> should give 'number'
ValueOf<Z, 'foo' | 'bar'> -> should give 'string' | 'number'
ValueOf<W, 'foo' | 'bar'> -> should give 'string'
ValueOf<Q, 'foo' | 'bar'> -> should give 'unknown'
我試過像這樣創建ValueOf
:
type ValueOf<T, K extends keyof any> = K extends keyof T ? T[K] : unknown;
但是,這不起作用,因為'foo' | 'bar'
'foo' | 'bar'
沒有擴展keyof X
因為X
沒有foo
和bar
作為鍵,所以結果是unknown
。 我需要的是從目標 object 中選擇任何匹配鍵並忽略 rest 的類型。 只有當沒有鍵匹配時,結果才應該是unknown
。
這可能嗎?
我得到的最接近的是將聯合類型拆分為多個 arguments,但這顯然不會變得靈活:
type ValueOf<T, K1 extends keyof any, K2 extends keyof any, K3 extends keyof any> =
K1 extends keyof T ? T[K1] :
K2 extends keyof T ? T[K2] :
K3 extends keyof T ? T[K3] :
unknown;
在這里,您必須始終准確地提供三個備用鍵名。 可以為K1, K2, K3
使用默認類型never
或any
,但無法默認為unknown
,因此這在一般情況下用處不大。
分布式條件類型的解決方案
分布式條件類型在實例化期間自動分布在聯合類型上。 例如,
T extends U? X: Y
T extends U? X: Y
類型參數A | B | C
A | B | C
T
的A | B | C
被解析為(A extends U? X: Y) | (B extends U? X: Y) | (C extends U? X: Y)
(A extends U? X: Y) | (B extends U? X: Y) | (C extends U? X: Y)
(A extends U? X: Y) | (B extends U? X: Y) | (C extends U? X: Y)
。
type SelectExistingKeysOf<T, K extends String> = K extends keyof T
? T[K]
: never;
type ValueOf<T, K extends String> = SelectExistingKeysOf<T, K> extends never
? unknown
: SelectExistingKeysOf<T, K>;
type test1 = ValueOf<X, 'foo' | 'bar'>; // string
type test2 = ValueOf<X, 'foo'>; // string
type test3 = ValueOf<X, 'bar'>; // unknown
type test4 = ValueOf<Z, 'foo' | 'bar'>; // string | number
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.