打字稿函数,其中对象具有由另一个参数确定的 属性 类型的字符串
Typescript function where object has a property of type string determined by another parameter
我想创建一个 TypeScript 函数,它接受一个对象和该对象中的 属性,其值为 string
。使用 <T, K extends keyof T>
可以确保只允许 T
的键作为 属性 的值,但我似乎无法缩小范围,因此键也必须指向 [=32] =] 类型 string
。这可能吗?
我试过这个:
function getKey<T extends {K: string}, K extends keyof T>(item: T, keyProperty: K): string {
return item[keyProperty];
}
但它只是说 Type 'T[K]' is not assignable to type 'string'
。为什么 T extends {K: string}
约束不能确保 T[K]
实际上是 string
,或者更确切地说,提供的 K
必须满足条件,以便 T[K]
是 string
?
明确地说,我希望能够像这样调用这个函数:
getKey({foo: 'VALUE', bar: 42}, 'foo') => return 'VALUE';
getKey({foo: 'VALUE', bar: 42}, 'bar') => should not be allowed since 'bar' is not a string property of the supplied object
getKey({foo: 'VALUE', bar: 'ANOTHER VALUE'}, 'bar') => return 'ANOTHER VALUE'
function getKey<T>(item: T, keyProperty: {[K in keyof T]: T[K] extends string ? K : never}[keyof T]): string {
return <string> <unknown> item[keyProperty];
}
有点笨重,但嗯..它有效。 :)
中,{K: string}
中的K
中只是string literal键的名称。这和你写 {"K": string}
:
是一样的
type Oops = { "K": string };
// type Oops = { K: string; }
由于您希望 K
成为密钥的 类型 ,因此您需要使用 mapped type, which iterates over some union of keys... either {[P in K]: string}
, or the equivalent Record<K, string>
using the Record<K, T>
utility type:
function getKey<T extends { [P in K]: string }, K extends keyof T>(
item: T,
keyProperty: K
): string {
return item[keyProperty]; // no error
}
并且您的调用代码的行为(大部分)符合您的预期:
getKey({ foo: 'VALUE', bar: 42 }, 'foo'); // okay
getKey({ foo: 'VALUE', bar: 42 }, 'bar'); // error!
// ----------------> ~~~
// number is not assignable to string
getKey({ foo: 'VALUE', bar: 'ANOTHER VALUE' }, 'bar'); // okay
我说 "mostly" 是因为您可能希望第二行中的错误出现在为 keyProperty
传入的 'bar'
值上,而实际发生的是错误在为 item
.
传入的值的 bar
属性 上
再花点心思就可以实现:
type KeysMatching<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
function getKey2<T extends { [P in K]: string }, K extends KeysMatching<T, string>>(
item: T,
keyProperty: K
): string {
return item[keyProperty];
}
在这里,我们不仅将 K
约束到 keyof T
,还约束到 T
的特定键,其值是 string
类型。我们使用自己的 KeysMatching<T, V>
实用程序类型来执行此操作。这不会改变最终有效的值,但它确实会改变编译器在某些内容无效时抱怨的地方:
getKey2({ foo: 'VALUE', bar: 42 }, 'foo');
getKey2({ foo: 'VALUE', bar: 42 }, 'bar'); // error!
// -----------------------------> ~~~~~
// "bar" is not "foo"
getKey2({ foo: 'VALUE', bar: 'ANOTHER VALUE' }, 'bar');
好的,希望对您有所帮助;祝你好运!
我想创建一个 TypeScript 函数,它接受一个对象和该对象中的 属性,其值为 string
。使用 <T, K extends keyof T>
可以确保只允许 T
的键作为 属性 的值,但我似乎无法缩小范围,因此键也必须指向 [=32] =] 类型 string
。这可能吗?
我试过这个:
function getKey<T extends {K: string}, K extends keyof T>(item: T, keyProperty: K): string {
return item[keyProperty];
}
但它只是说 Type 'T[K]' is not assignable to type 'string'
。为什么 T extends {K: string}
约束不能确保 T[K]
实际上是 string
,或者更确切地说,提供的 K
必须满足条件,以便 T[K]
是 string
?
明确地说,我希望能够像这样调用这个函数:
getKey({foo: 'VALUE', bar: 42}, 'foo') => return 'VALUE';
getKey({foo: 'VALUE', bar: 42}, 'bar') => should not be allowed since 'bar' is not a string property of the supplied object
getKey({foo: 'VALUE', bar: 'ANOTHER VALUE'}, 'bar') => return 'ANOTHER VALUE'
function getKey<T>(item: T, keyProperty: {[K in keyof T]: T[K] extends string ? K : never}[keyof T]): string {
return <string> <unknown> item[keyProperty];
}
有点笨重,但嗯..它有效。 :)
中,{K: string}
中的K
中只是string literal键的名称。这和你写 {"K": string}
:
type Oops = { "K": string };
// type Oops = { K: string; }
由于您希望 K
成为密钥的 类型 ,因此您需要使用 mapped type, which iterates over some union of keys... either {[P in K]: string}
, or the equivalent Record<K, string>
using the Record<K, T>
utility type:
function getKey<T extends { [P in K]: string }, K extends keyof T>(
item: T,
keyProperty: K
): string {
return item[keyProperty]; // no error
}
并且您的调用代码的行为(大部分)符合您的预期:
getKey({ foo: 'VALUE', bar: 42 }, 'foo'); // okay
getKey({ foo: 'VALUE', bar: 42 }, 'bar'); // error!
// ----------------> ~~~
// number is not assignable to string
getKey({ foo: 'VALUE', bar: 'ANOTHER VALUE' }, 'bar'); // okay
我说 "mostly" 是因为您可能希望第二行中的错误出现在为 keyProperty
传入的 'bar'
值上,而实际发生的是错误在为 item
.
bar
属性 上
再花点心思就可以实现:
type KeysMatching<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
function getKey2<T extends { [P in K]: string }, K extends KeysMatching<T, string>>(
item: T,
keyProperty: K
): string {
return item[keyProperty];
}
在这里,我们不仅将 K
约束到 keyof T
,还约束到 T
的特定键,其值是 string
类型。我们使用自己的 KeysMatching<T, V>
实用程序类型来执行此操作。这不会改变最终有效的值,但它确实会改变编译器在某些内容无效时抱怨的地方:
getKey2({ foo: 'VALUE', bar: 42 }, 'foo');
getKey2({ foo: 'VALUE', bar: 42 }, 'bar'); // error!
// -----------------------------> ~~~~~
// "bar" is not "foo"
getKey2({ foo: 'VALUE', bar: 'ANOTHER VALUE' }, 'bar');
好的,希望对您有所帮助;祝你好运!