将 Type 约束为 T 的键并且是特定类型
Constrain Type to be a keyof T and to be a specific type
考虑
export function sortByProp<T extends Record<string, any>>(propName: keyof T) {
return sort((a, b) => a[propName].localeCompare(b[propName]))
我希望确保 propName
也是一个类型 string
结果
Property 'localeCompare' does not exist on type 'unknown'.ts(2339)
这是如何实现的?
好的,这让我更进一步:
export const sortByProp = <T extends Record<string, any>>(propName: keyof T) => {
return sort<T>((a, b) => a[propName].localeCompare(b[propName]))
}
消耗
sortByProp('hostname')(data.devices.devicePageEntries).map(x => ({
key: x.id,
value: x.hostname,
}))
但后来我得到
Property 'id' does not exist on type '{ hostname: any; }
在我的调用方方法中进行转换似乎可以解决问题,
(sortByProp('hostname')(
data.devices.devicePageEntries,
) as DevicePageEntry[])
我正在使用 Ramda 0.25.0
这是一个可能的解决方案:
import { sort } from "ramda";
export function sortByProp<K extends string>(propName: K) {
return <T extends Record<K, string>>(arr: T[]) =>
sort((a: T, b: T) => a[propName].localeCompare(b[propName]))(arr);
}
const result = sortByProp("hostname")([
{ hostname: "foo", id: 1 },
{ hostname: "bar", id: 2 }
]);
// [{"hostname":"bar","id":2},{"hostname":"foo","id":1}]
const mappedResult = result.map(x => ({
key: x.id, // works
value: x.hostname
}));
// [{"key":2,"value":"bar"},{"key":1,"value":"foo"}]
我用约束 extends Record<K, string>
声明了类型参数 T
以确保 localeCompare
总是在 string
属性 值上被调用。
此外,编译器无法通过查看函数声明签名(参数和 return 类型来收集 generic type parameter T
by solely looking at function parameter propName: keyof T
, so it takes any
from T
's base constraint Record<string, any>
. Further reason is: Inference candidates 和 T
的 属性 值类型),而不是函数 body/implementation。 TypeScript 也只直接咨询带有 T
注释的函数,而不是内部函数声明,以供可能的候选者使用。
通过将 T
声明为内部函数的一部分,TypeScript 可以利用函数参数 arr: T[]
来推断 T
.
另类 sort
纯 JS
function sort<T>(cb: (t1: T, t2: T) => number) {
return (arr: T[]) => [...arr].sort(cb);
}
考虑
export function sortByProp<T extends Record<string, any>>(propName: keyof T) {
return sort((a, b) => a[propName].localeCompare(b[propName]))
我希望确保 propName
也是一个类型 string
结果
Property 'localeCompare' does not exist on type 'unknown'.ts(2339)
这是如何实现的?
好的,这让我更进一步:
export const sortByProp = <T extends Record<string, any>>(propName: keyof T) => {
return sort<T>((a, b) => a[propName].localeCompare(b[propName]))
}
消耗
sortByProp('hostname')(data.devices.devicePageEntries).map(x => ({
key: x.id,
value: x.hostname,
}))
但后来我得到
Property 'id' does not exist on type '{ hostname: any; }
在我的调用方方法中进行转换似乎可以解决问题,
(sortByProp('hostname')(
data.devices.devicePageEntries,
) as DevicePageEntry[])
我正在使用 Ramda 0.25.0
这是一个可能的解决方案:
import { sort } from "ramda";
export function sortByProp<K extends string>(propName: K) {
return <T extends Record<K, string>>(arr: T[]) =>
sort((a: T, b: T) => a[propName].localeCompare(b[propName]))(arr);
}
const result = sortByProp("hostname")([
{ hostname: "foo", id: 1 },
{ hostname: "bar", id: 2 }
]);
// [{"hostname":"bar","id":2},{"hostname":"foo","id":1}]
const mappedResult = result.map(x => ({
key: x.id, // works
value: x.hostname
}));
// [{"key":2,"value":"bar"},{"key":1,"value":"foo"}]
我用约束 extends Record<K, string>
声明了类型参数 T
以确保 localeCompare
总是在 string
属性 值上被调用。
此外,编译器无法通过查看函数声明签名(参数和 return 类型来收集 generic type parameter T
by solely looking at function parameter propName: keyof T
, so it takes any
from T
's base constraint Record<string, any>
. Further reason is: Inference candidates 和 T
的 属性 值类型),而不是函数 body/implementation。 TypeScript 也只直接咨询带有 T
注释的函数,而不是内部函数声明,以供可能的候选者使用。
通过将 T
声明为内部函数的一部分,TypeScript 可以利用函数参数 arr: T[]
来推断 T
.
另类 sort
纯 JS
function sort<T>(cb: (t1: T, t2: T) => number) {
return (arr: T[]) => [...arr].sort(cb);
}