[英]Typescript - How to use generics to define a function that returns indexable properties of an object?
I am having trouble writing the correct types for a simple function.我无法为简单函数编写正确的类型。
I want to create a function that when given a key ( keyof any
) or callback will return another function.我想创建一个函数,当给定一个键(
keyof any
)或回调时将返回另一个函数。 This function takes in some data and returns another key.此函数接收一些数据并返回另一个键。
In other words both toKey('propertyName')
and toKey(value => value.propertyName)
would return the function value => value.propertyName
.换句话说,
toKey('propertyName')
和toKey(value => value.propertyName)
都会返回函数value => value.propertyName
。 When called, the function would return the given value of said property only if the value is a string
, number
or symbol
type.调用时,该函数将仅在值为
string
、 number
或symbol
类型时返回所述属性的给定值。
Here's an example:下面是一个例子:
function toKey(keyIdentity) { /* snippet */ }
interface IPerson {
firstName: string,
lastName: string,
age: number,
emails: string[]
};
const getKey1 = toKey((person: IPerson) => person.emails[0]);
const getKey2 = toKey('firstName');
const getKey3 = toKey('emails');
const person: IPerson = {
firstName: 'Craig',
lastName: 'Lipton',
age: 46,
emails: [
'<email-1>',
'<email-2>'
]
};
getKey1(person); // returns "<email-1>";
getKey2(person); // returns "Craig";
getKey3(person); // not allowed;
I've attempted to use generics and overloads to achieve the correct typing but it gets complicated very quickly.我尝试使用泛型和重载来实现正确的输入,但很快就会变得复杂。
function toKey(key?: null): () => void;
function toKey<K extends keyof any>(key: K): <U extends keyof any>(item: Record<K, U>) => U;
function toKey<T extends (...args: any[]) => keyof any>(key: T): T;
function toKey(key: any): any {
if (isNil(key)) {
return noop;
}
return isFunction(key) ? key : (value: T) => value[key];
}
Is there any simpler way to write this?有没有更简单的方法来写这个?
If you want to be explicit in your types, the built-in PropertyKey
type can be used:如果你想在你的类型中显式,可以使用内置的
PropertyKey
类型:
// type PropertyKey = string | number | symbol
function toKey<K extends PropertyKey>(key: K):
<T extends Record<K, PropertyKey>>(t: T) => PropertyKey
function toKey<T>(fn: (t: T) => PropertyKey): (t: T) => PropertyKey
function toKey(key: PropertyKey | ((t: Record<PropertyKey, PropertyKey>) => PropertyKey)) {...}
Test it:测试一下:
toKey((person: IPerson) => person.emails[0])(person); // "<email-1>";
toKey('firstName')(person); // "Craig";
toKey('emails')(person); // error, emails prop is not string | number | symbol
toKey('lastName')({ firstName: "Lui" }); // error, object passed in has no key "lastName"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.