将通用类型属性过滤为特定类型

时间:2019-05-20 20:06:06

标签: typescript

我试图找到一种方法来告诉TypeScript的编译器,一个值是(深呼吸)一个通用类型的键,如果将其应用于该类型的对象,它将导致a的属性。具体类型。我知道这句话确实令人困惑,所以这是一个具体的例子。

const obj: T = an object of type T;
const key: KeysMatching<T, U> = a key that matches `typeof T[key] === U`;
const attribute = obj[key];

在这里,我希望attribute的类型为U或可分配给类型U

我从TypeScript文档中提供的Filter helper中得到了启发,尝试使用this answer中提出的类型似乎很适合我的情况(但显然不是),最后尝试了创建自己的帮助程序,以过滤某些类型的属性:

type KeysMatching<T, U> = T[keyof T] extends U ? keyof T : never;

当前,在我的自定义解决方案中,attribute的类型为T[T[keyof T] extends U ? keyof T : never],并且无法分配给U

有没有一种方法可以实现我想做的事情?

我试图给出一个可重现的案例,但是如果您需要更多信息,上下文或实际案例,请随时提问!

在此先感谢任何可能给我一些想法或解决方案的人。

1 个答案:

答案 0 :(得分:1)

在条件类型打字稿中使用泛型类型参数时,只要它们中仍然存在未解析的类型参数,就无法对其进行太多推理。这就是为什么从通用类/函数的外部可以按预期运行但在内部仍无法正常运行的情况下,编译器不允许您对此类类型执行很多操作的原因:

type KeysMatching<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];

function test<T, K extends KeysMatching<T, string>>(o: T, k: K): T[K] {
    let v = o[k];

    v.toLowerCase() // error 
    return v;
}
test({ a: ""}, "a").toLowerCase() // ok from outside

有时您可以通过约束T而不是K来解决此问题。

function test<T extends Record<K, string>, K extends PropertyKey>(o: T, k: K): T[K] {
    let v = o[k];
    v.toLowerCase(); //ok
    return v
}

这确实有局限性,因为示例intelisense不会显示K的建议。