Typescript 中的元组参数类型推断

Tuple argument type inference in Typescript

是否可以在 Typescript 中实现以下功能:

我希望根据 takeConfig 的输入将 state.initial 的类型推导为元组。根据组件参数的 state 属性 类型推导 return 类型的 initialState 函数也很好(尽管我认为如果没有API).

的改动
type State1 = { a: string };
type State2 = { b: string };

function Component1(props: { state: State1 }) {}
function Component2(props: { state: State2 }) {}

const state = takeConfig([
    {
        component: Component1,
        initialState: () => ({
            a: "a"
        }) // return type here is deduced to be State1
    },
    {
        component: Component2,
        initialState: () => ({
            b: "b"
        }) // return type here is deduced to be State2
    },
]);


// type here is deduced to be [State1, State2]
state.initial

谢谢!

If your question is "is it possible" and not "how to do it" then the answer is yes.

让我们首先定义您的 takeConfig 函数将采用的对象类型:

type Conf<C extends (...args: any[]) => any> = {
    component: C;
    initialState: () => Parameters<C>[0]["state"];
};

然后我们将创建一个类型来推断元组中的所有组件函数类型:

type InferConfs<C extends ReadonlyArray<unknown>> = {
    [K in keyof C]: C[K] extends Conf<infer Comp> ? Conf<Comp> : C[K];
};

接下来我们需要一个类型来以类似于 InferConfs:

的方式为我们提供 state.initial
type JustStates<C extends ReadonlyArray<unknown>> = {
    [K in keyof C]: C[K] extends Conf<infer _> ? ReturnType<C[K]["initialState"]> : C[K];
};

最后让我们创建一个类型来保存 JustStates:

type ReturnedState<Confs extends ReadonlyArray<unknown>> = {
    initial: JustStates<Confs>;
};

还有一种删除 readonly 的类型,as const 将给出:

type MakeNotReadonly<T> = {
    -readonly [K in keyof T]: T[K];
};

现在我们将所有这些放在一起来定义我们的 takeConfig 函数:

function takeConfig<C extends ReadonlyArray<unknown>>(conf: InferConfs<C>): ReturnedState<MakeNotReadonly<InferConfs<C>>> { ... }

但是,您必须自己实现该功能。我只是在帮助类型。

基本原理是 TypeScript 可以推断出我们传递给 takeConfig 的一般类型,我们使用 InferConfs 进一步缩小配置的类型。然后在 return 类型中我们再次推断配置,然后对其进行一些类型转换 (JustState) 和 return 它。

Playground