【问题标题】:Filter generic type properties to specific type将泛型类型属性过滤到特定类型
【发布时间】:2019-05-21 04:50:55
【问题描述】:

我正在尝试找到一种方法来告诉 TypeScript 的编译器一个值是(深呼吸)一个泛型类型的键,如果应用于该类型的对象,将产生一个属性具体类型。我知道这句话真的很混乱,所以这里有一个具体的例子。

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

有没有办法实现我想做的事情?

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

提前感谢任何能给我一些想法或解决方案的人。

【问题讨论】:

  • 这个泛型类型是在函数还是类的上下文中?

标签: typescript


【解决方案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 的建议。

【讨论】:

  • 感谢您的澄清!在我的情况下,我认为 a 不能使用您的解决方法,因为我需要我的类型来允许其他属性。这次我可能会坚持使用糟糕的as unknown as U
  • @EnzoBaldisserri 上面的选项将允许额外的属性,它只会将K 指定的属性限制为string
  • 哦,好吧,我没有意识到这一点。到时候我会想办法让它适应。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
相关资源
最近更新 更多