gpt4 book ai didi

typescript - 如何扩展 keyof 类型以使其包含 key 的修改版本,例如以 '-' 为前缀?

转载 作者:行者123 更新时间:2023-12-04 12:09:06 25 4
gpt4 key购买 nike

例如,我想将 Typescript 类型安全添加到 vanilla Javascript Sort array of objects by string property value解决方案。它接受要排序的对象的 args 键,以确定要排序的键。如果 key 以 - 为前缀,排序相反。
我将如何输入 arg 以接受,例如,"age""-age" ?
这是我的尝试:

export function dynamicSortMultiple<T extends object, U extends keyof T>(
props: Array<U>,
) {
function dynamicSort(key: U) {
let sortOrder = 1
if (typeof key === 'string' && key.startsWith('-')) {
sortOrder = -1
}
return function (a: T, b: T) {
const result = a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : 0

return result * sortOrder
}
}

return function (obj1: T, obj2: T) {
let i = 0
let result = 0
const numberOfProperties = props?.length
while (result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2)
i++
}

return result
}
}

export interface User {
userId: string
firstName: string
lastName: string
login: string
password: string
rank: number
score: number
age?: number
}

dynamicSortMultiple<User, keyof User>(['firstName', 'score', '-age'])

typescript playground
在最后一行我看到错误
Type '"-age"' is not assignable to type 'keyof User'.
有什么方法可以扩展 keyof User是否正确,以便以“-”为前缀的值仍被视为该类型的有效值?
即使您完全更换我的解决方案,我也会很感激。

最佳答案

我的变化:

  • T 和 U 通用参数是多余的。只需要T。

    Note: I originally just replaced all your U references withkeyof T, but then pulled it out to sortArg to facilitate#2.


  • 使用 Template Literal Types在 TS 4.1 中引入
  • 您忘记修剪 - startsWith('-') 情况下的前缀
  • 在 Typescript 无法缩小类型的地方使用类型断言
    必须给它的逻辑流程(TS 团队一直在改进
    TS 编译器的流程分析,所以我打赌有一天这将是自动的)
  • API 改进:重命名函数并添加一个方便的sort在代码中读取更好的函数(参见示例用法
    遵循解决方案代码)。

  • type sortArg<T> = keyof T | `-${string & keyof T}`

    /**
    * Returns a comparator for objects of type T that can be used by sort
    * functions, were T objects are compared by the specified T properties.
    *
    * @param sortBy - the names of the properties to sort by, in precedence order.
    * Prefix any name with `-` to sort it in descending order.
    */
    export function byPropertiesOf<T extends object> (sortBy: Array<sortArg<T>>) {
    function compareByProperty (arg: sortArg<T>) {
    let key: keyof T
    let sortOrder = 1
    if (typeof arg === 'string' && arg.startsWith('-')) {
    sortOrder = -1
    // Typescript is not yet smart enough to infer that substring is keyof T
    key = arg.substr(1) as keyof T
    } else {
    // Likewise it is not yet smart enough to infer that arg is not keyof T
    key = arg as keyof T
    }
    return function (a: T, b: T) {
    const result = a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : 0

    return result * sortOrder
    }
    }

    return function (obj1: T, obj2: T) {
    let i = 0
    let result = 0
    const numberOfProperties = sortBy?.length
    while (result === 0 && i < numberOfProperties) {
    result = compareByProperty(sortBy[i])(obj1, obj2)
    i++
    }

    return result
    }
    }

    /**
    * Sorts an array of T by the specified properties of T.
    *
    * @param arr - the array to be sorted, all of the same type T
    * @param sortBy - the names of the properties to sort by, in precedence order.
    * Prefix any name with `-` to sort it in descending order.
    */
    export function sort<T extends object> (arr: T[], ...sortBy: Array<sortArg<T>>) {
    arr.sort(byPropertiesOf<T>(sortBy))
    }
    用法示例:
    interface User {
    name: string
    id: string
    age?: number
    }

    const users: User[] = [
    {name: 'Harriet Tubman', id: '01', age: 53},
    {name: 'John Brown', id: '02', age: 31},
    {name: 'John Brown', id: '03', age: 59},
    {name: 'James Baldwin', id: '04', age: 42},
    {name: 'Greta Thunberg', id: '05', age: 17}
    ]

    // using Array.sort directly
    users.sort(byPropertiesOf<User>(['name', '-age', 'id']))

    // using the convenience function for much more readable code
    sort(users, 'name', '-age', 'id')

    关于typescript - 如何扩展 keyof 类型以使其包含 key 的修改版本,例如以 '-' 为前缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68278850/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com