打字稿选择字符串属性

时间:2021-06-22 14:15:58

标签: typescript tsc

我试图弄清楚如何正确键入一个 show 函数,该函数将接受一个对象 T 和一个键 KT[K] 可以保证实现了 toString() 方法。

这是我尝试使用映射类型

type ToStringablePropertyKeys<T> = keyof {
    [K in keyof T]: { toString(): string }
}

function show<T, K extends ToStringablePropertyKeys<T>>(t: T, k: K): string {
    return t[k].toString()
}

但是编译器说Property 'toString' does not exist on type 'T[K]'.

我在这里错过了什么?我如何说服 tsc 根据 toString 的定义,K 实际上存在?

2 个答案:

答案 0 :(得分:5)

另一种方法:

function show<K extends string, T extends {[key in K]:{toString(): string}}>
(t: T, k: K ): string {
return t[k].toString()
}

答案 1 :(得分:2)

这是一个几乎理想的解决方案。尽管打字稿可以强制密钥仅是在 {toString():string} 上展开的密钥,但从那里推断出所有 T[k] 都将具有 toString():string...

type ToStringable = { toString(): string };

type ToStringablePropertyKeys<T> = {
    [k in keyof T]: T[k] extends ToStringable ? k : never
}[keyof T];

function show<T, K extends ToStringablePropertyKeys<T>>(t: T, k: K): string {
    return (t[k] as any).toString(); // it seems typescript is not smart enough to infer that all t[k] will have toString
}

const testObject = {
    string: 'test',
    number: 123,
    null: null,
    undefined: undefined,
};

show(testObject, 'number');
show(testObject, 'string');
show(testObject, 'invalid-prop'); //this fails
show(testObject, 'null'); //this fails
show(testObject, 'undefined'); //this fails

https://www.typescriptlang.org/play?ts=4.3.4#code/C4TwDgpgBAKg9gZWAJwJYDsDmBDARgG2gF4oBvKYRFDTACgEoAuKAZ2qygF8BuAKF9CRYVNFjyEACsjiRkoANIQQLADwwAfFBKleUPVADaAaygYoRpXABmsALrMYx21AgAPYBHQATFsKSicAmgAfnMoZnQIADcIZF5OY0sbGFs+XisAV3QAY2BUOHRWAAs4AHc1ABooeRd3Tx8-dkDJaVkFJVUNdVpgByqjZnkmViayXX1kCGAM5EKepyhsX2x0EHoAOkp-GgZuKAB6fdNgVggIAFtfQQgWbLQwE9RfdDgTlnPsORcXjMwiijgpnQVliFCK2BO2Hw+AoC1KqGhUHBMQB2yw8X42QKbAoN2AAHlcAArCC5LRjfQjALMADkHjYNIq4z06Ay51wsWYAEYAEwAZiZlNZ0IiGWhgv0WS8ECsGAgXmYUplcq8TJ4-BYJVKPTxhJJuSqNNZ7NiNPofE1ZR1bD1pOAhrYATNFq11oJxLthowUShqC8AFowK1nQd9sAik8oFZsAiWLxLdr6e79faoEaxfgQ4dw5Ho7H466k7aDWmlbLIl4s2GI748-g40A