【问题标题】:How can I tell Typescript to check that object[key] is of certain type?如何告诉 Typescript 检查 object[key] 是否属于某种类型?
【发布时间】:2021-07-04 14:42:47
【问题描述】:

假设我有一个这样的 Typescript 函数:

const myFunction = <U, V extends keyof U> (object: U, key: V) => {
    // ...
}

如何让 Typescript 检查 object[key] 是否属于某种类型?

例如,假设我希望 object[key] 为“字符串”类型。

所以,当我打电话给myFunction 时,它应该是这样工作的:

myFunction({keyA: "hello", keyB: 123}, "keyA") // OK

myFunction({keyA: "hello", keyB: 123}, "keyB") // error: `keyB` must be of type string but is number

【问题讨论】:

    标签: typescript types typescript-generics


    【解决方案1】:

    根据In TypeScript, how to get the keys of an object type whose values are of a given type? 的答案,我整理了这个工作示例,专门回答了您的问题(see playground),但困难的部分确实来自另一个答案。

    type KeysMatching<T,V> = keyof { [ P in keyof T as T[P] extends V ? P : never ] : P };
    
    function myFunction<T>(object: T, key: KeysMatching<T,string> ){
        // ...
    }
    
    myFunction({keyA: "hello", keyB: 123}, "keyA") // OK
    
    myFunction({keyA: "hello", keyB: 123}, "keyB") // error: `keyB` must be of type string but is number
    

    我非常喜欢提取 PickValues&lt;T,V&gt; 类型的形式,它将 T 的属性过滤为仅具有 V 中的值的属性。然后只需在上面使用 keyof...

    type PickValues<T,V> = { [ P in keyof T as T[P] extends V ? P : never ] : T[P] }
    type Picked = PickValues<{keyA: "hello", keyB: 123},string>;
    // type Picked = {
    //     keyA: "hello";
    // }
    
    //Your case
    function myFunction<T>(object: T, key: keyof PickValues<T,string> ){
        // ...
    }
    myFunction({keyA: "hello", keyB: 123}, "keyA") // OK
    myFunction({keyA: "hello", keyB: 123}, "keyB") // error: `keyB` must be of type string but is number
    

    顺便说一句,这个策略可以被推广到做相反的事情并创建一个OmitValues&lt;T,V&gt; 类型......

    type OmitValues<T,V> = { [ P in keyof T as T[P] extends V ? never : P ] : T[P] }
    type Omitted = OmitValues<{keyA: "hello", keyB: 123},string>;
    // type Omitted = {
    //     keyB: 123;
    // }
    

    最后,它也可以重新用于仅提取具有可选性质的属性...

    type OptionalValues<T> = { [ P in keyof T as undefined extends T[P] ? P : never ] : T[P] }
    type Optional = OptionalValues<{keyA?: "hello", keyB: 123}>;
    // type Optional = {
    //     keyA?: "hello" | undefined;
    // }
    

    【讨论】:

    • 这是一个非常鼓舞人心且具有挑战性的问题(尽管看起来非常简单)。它教会了我关于 Typescript 的新知识。从那里开始,我一直在努力完善上面的答案。我发现构造实用程序类型 PickValues 和 OmitValues 是推理问题和定义键联合的好方法。我还发现我可以提取 OptionalValues。操场在tsplay.dev/m3AV2w
    • 它并没有真正改变答案,但以不同的方式编写它有助于我更好地遵循解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 2010-10-31
    • 2011-09-10
    • 2010-12-25
    • 2023-02-07
    • 2011-03-25
    • 2022-01-08
    相关资源
    最近更新 更多