简体   繁体   English

从同级键的值推断对象键类型

[英]Infer object key type from sibling key's value

I have an Object Type Options with two keys:我有一个带有两个键的对象类型Options

  1. strategy : a function that requires one parameter of unknown type strategy :需要一个未知类型参数的函数
  2. parameter : same type as strategy 's first argument parameter :与strategy的第一个参数相同的类型

I want to be able to do the following我希望能够做到以下几点

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' }
}

The type fooOptions.parameter should be inferred from fooOptions.strategy and barOptions.parameter from barOptions.strategy类型fooOptions.parameter应该从fooOptions.strategybarOptions.parameterbarOptions.strategy推断

Is that possible with TypeScript today?今天的 TypeScript 有可能实现吗?

The only way I can imagine to do this is using a generic type.我能想象到的唯一方法是使用泛型类型。 I think it's unlikely there is a solution where the compiler will check that parameter is a suitable argument for strategy without using a generic type.我认为不太可能有一个解决方案,编译器会在不使用泛型类型的情况下检查该parameter是否是strategy的合适参数。

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

This means that if Options is used in a type annotation then you have to provide a type parameter:这意味着如果在类型注释中使用了Options ,那么您必须提供一个类型参数:

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

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

However, anywhere you allow the compiler to infer the type (ie whenever you don't use a type annotation), it is not necessary to provide an explicit type for the generic type parameter.但是,在允许编译器推断类型的任何地方(即,无论何时不使用类型注释),都没有必要为泛型类型参数提供显式类型。 In particular, users of an API such as the useOptions function can pass an object literal, and enjoy the benefits of type-checking and type inference:特别是,像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' }
});

Note that the user in this example doesn't have to explicitly write { x: number, y: string } or an equivalent type in order to use the API.请注意,此示例中的用户不必显式编写{ x: number, y: string }或等效类型来使用 API。

Playground Link 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM