【问题标题】:Infer object key type from sibling key's value从兄弟键的值推断对象键类型
【发布时间】:2020-01-20 17:50:36
【问题描述】:

我有一个对象类型Options,有两个键:

  1. strategy:需要一个未知类型参数的函数
  2. parameter:与strategy的第一个参数类型相同

我希望能够做到以下几点

type FooParameter = { foo: string }
type BarParameter = { bar: string }

const fooOptions: Options = {
  strategy: (parameter: FooParameter) => {},
  parameter: { foo: 'foo' }
}
const barOptions: Options = {
  strategy: (parameter: BarParameter) => {},
  parameter: { bar: 'bar' }
}

fooOptions.parameter 的类型应该从 fooOptions.strategy 推断出来,barOptions.parameterbarOptions.strategy 推断出来

现在的 TypeScript 可以做到吗?

【问题讨论】:

  • 与其推断,为什么不让Options泛型呢?例如。 type Options<T> = { strategy: (parameter: T) => void, parameter: T }.
  • 我应该添加,我试过了:typescriptlang.org/play/… 但我想避免传递参数类型的需要
  • 上下文是github.com/octokit/core.js#authenticationauthStrategyauth 选项。 authStrategy 设置为外部包,参数类型未知。因此推断它会比使用类型参数提供更好的开发者体验。
  • Typescript 可以推断泛型类型的类型参数,因此调用者不需要显式编写该类型。我应该更清楚的是,这不是您的库推断它,而不是推断用户的数据类型。您的文档中的示例用法看起来应该适用于泛型类型,而无需对示例用法代码进行任何更改。
  • “Typescript 可以推断泛型类型的类型参数”这听起来像我想要的,但无法弄清楚如何。您能否在下面的答案中分享一个示例?

标签: typescript


【解决方案1】:

我能想到的唯一方法是使用泛型类型。我认为编译器不太可能在不使用泛型类型的情况下检查parameter 是否是strategy 的合适参数。

type Options<T> = {
    strategy: (parameter: T) => void,
    parameter: T
}

这意味着如果Options 用在类型注解中,那么你必须提供一个类型参数:

const fooOptions: Options<FooParameter> = {
    strategy: (parameter: FooParameter) => {},
    parameter: { foo: 'foo' }
}

function useOptions<T>(o: Options<T>): void {
    o.strategy(o.parameter);
}

但是,在您允许编译器推断类型的任何地方(即,当您不使用类型注释时),都没有必要为泛型类型参数提供显式类型。特别是,useOptions 函数等 API 的用户可以传递对象字面量,并享受类型检查和类型推断的好处:

useOptions({
    strategy: param => {
        let x = param.x; // Inferred as number
        let y = param.y; // Inferred as string

        // Error: Property 'z' does not exist on type '{ x: number, y: string }'
        let z = param.z;
    },
    parameter: { x: 1, y: 'foo' }
});

请注意,此示例中的用户不必显式编写 { x: number, y: string } 或等效类型即可使用 API。

Playground Link

【讨论】:

  • useOptions 示例中,似乎param 方法参数的类型是从parameter 推断出来的。我正在寻找相反的东西。有什么想法吗?
  • 两者都将从另一个推断。如果您使用strategy: (param: FooParameter) =&gt; {} 调用它,那么它将检查parameter 的类型是否为FooParameter
猜你喜欢
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 2019-08-12
  • 2021-02-25
  • 2022-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多