【问题标题】:Type to represent the keys of an object that have specific value type in Typescript类型以表示在 Typescript 中具有特定值类型的对象的键
【发布时间】:2018-10-12 22:57:27
【问题描述】:

我有一个函数,它接受一个带有两个键的配置对象。这些值是对象中的键数组。

Config 类型上的 a 值将从 T 类型的对象中删除,但 b 值需要以某种仅对字符串值键有效的方式进行转换.

结果是一个将T类型作为显式参数的函数,并返回一个对T类型的对象进行转换的函数:

interface Config<T extends Object, K extends keyof T> {
  a?: K[]  // keys to remove from T, this works fine
  b?: K[]  // keys to modify string value - want to constrain these
}

export function f<T extends Object>(config: Config<T, keyof T>): (row: T) => Partial<T> {
  return function (row) {
    // remove keys from config.a
    // do something stringy with keys from config.b
  }
}

它是这样称呼的:

const fn = f<SomeType>({ a: [...], b: [...] })

有什么方法可以将Config 接口中的b 限制为只有字符串值的键?我尝试了所有我能想到的方法,但我尝试的大部分方法都产生了语法错误。我现在正在通过将字符串值强制为字符串来解决这个问题,因为类型系统不知道它们是字符串。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    如果您不需要跟踪要删除/添加的键的实际联合,则可以从 Config 中删除 K 参数。从您的示例中,我认为不需要。

    要仅获取特定类型的键,我们可以使用条件类型和映射类型:

    interface Config<T extends Object> {
        a?: (keyof T)[]  // keys to remove from T, this works fine
        b?: KeyOfValueType<T, string>[]  // keys to modify string value - want to constrain these
    }
    type KeyOfValueType<T, TValue> = {[P in keyof T]: T[P] extends TValue ? P : never}[keyof T];
    
    
    export function f<T extends Object>(config: Config<T>): (row: T) => Partial<T> {
        return function (row) {
    
            return null as any;
        }
    }
    interface SomeType {
        nr: number;
        str: string
    }
    const fnOk = f<SomeType>({ a: ['nr'], b: ['str' ] })
    const fnNok = f<SomeType>({ a: ['nr'], b: ['str', 'nr'] })
    

    【讨论】:

    • 是的,有一次我没有额外的参数,但我试图用K 做恶作剧并把它留在里面。我接近你所拥有的但错过了关键步骤介绍另一种类型。谢谢!
    • row[b] 仍然不能分配给string...有什么想法吗?
    • @KeithLayne 我认为可以做到,但我们将不得不稍微改变方法。我会更新答案
    • @KeithLayne 不幸的是,我想到的方法在这种情况下不起作用。恐怕我们无法说服编译器 row[b] 是字符串,除非通过类型断言。不幸的是,您将不得不满足于呼叫站点类型的安全性。
    • 这仍然是一个重大改进,我会接受它。
    猜你喜欢
    • 2019-05-08
    • 2021-01-18
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    相关资源
    最近更新 更多