Typescript 中的强类型问题

Issue with strong typing in Typescript

我有以下代码:

export type FooParams = {
  foo1: { x: number };
  foo2: { y: string };
};

export type FooKey = keyof FooParams; // or export type FooKey = "foo1" | "foo2";

export interface FooAction<T extends FooKey> {
  execute: (params: FooParams[T]) => void;
}

const foo1Action: FooAction<"foo1"> = {
  execute: (params) => {
    console.log(params.x);
  },
};

const foo2Action: FooAction<"foo2"> = {
  execute: (params) => {
    console.log(params.y);
  },
};

export const fooActions: Record<FooKey, FooAction<FooKey>> = {
  foo1: foo1Action,
  foo2: foo2Action,
};

我无法强键入变量 fooActions,以便为每个 FooKey 强制输入 FooAction。在上面的示例中,我有以下错误。

Type 'FooAction<"foo1">' is not assignable to type 'FooAction<keyof FooParams>'.
  Type 'keyof FooParams' is not assignable to type '"foo1"'.
    Type '"foo2"' is not assignable to type '"foo1"'.ts(2322)

知道如何正确声明 fooActions 类型吗?

FooAction<FooKey> 意味着 execute 将具有类型 (params: FooParams[FooKey]) => void,后者又将解析为 (params: { x: number } | { y: string }) => void;。这意味着它必须是一个同时处理 { x: number }{ y: number } 的函数。因此,Record<FooKey, FooAction<FooKey>> 类型对象的所有值都必须处理两种类型,而 foo1Actionfoo2Action 只能处理一种类型。

您想键入 fooActions 键和类型之间的相关性。您可以使用自定义映射类型来做到这一点:

type FooActionMap = {
    [P in FooKey]: FooAction<P>
}
export const fooActions: FooActionMap  = {
  foo1: foo1Action,
  foo2: foo2Action,
};

Playground Link