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 它。
是否可以在 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 它。