具有通用结果语法错误的 TypeScript 对象类型

TypeScript object type with generic result syntax error

尝试将泛型 Merge 的结果赋值到对象类型(键值类型)时出现语法错误:

type Merge<a,b> = any

type test<P, S= any, K= any> = {
    jsx1?: (state: Merge<K, S>, props: P, nextJsx?) => JSX.Element; //ok
    jsx2?: ({state: S, props: P, nextJsx}) => JSX.Element; // ok
    jsx3?: ({ state: Merge<K, S>, props: P, nextJsx }) => JSX.Element; // error - why?
    //                    ^ WebStorm: ", expected"     ^ VSCode: ';' expected.(1005)
};

为什么认为是语法错误?如何将 jsx3->state 分配给类型 Merge

打字稿 4.4.4.

TS 游乐场:

Playground

您在 jsx2jsx3 中解构具有不同名称的对象,而不是键入它们。在 jsx3 的情况下,这是无效语法。您要做的是正确键入函数参数:

type Merge<A,B> = any;

type JSX2Args<P, S> = {
    state: S,
    props: P,
    nextJsx: unknown
}

type JSX3Args<P, S, K> = {
    state: Merge<K, S>,
    props: P,
    nextJsx: unknown
}

type test<P, S= any, K= any> = {
    jsx1?: (state: Merge<K, S>, props: P, nextJsx?) => JSX.Element;
    jsx2?: (arg: JSX2Args<P, S>) => JSX.Element; 
    jsx3?: ({ state, props, nextJsx }: JSX3Args<P, S, K>) => JSX.Element;
};

在签名({state: S, props: P, nextJsx}) => JSX.Element中,SP不是类型,它们是标识符。在此上下文中,冒号 : 并不表示类型注释,而是表示重新绑定 属性 的名称,如下例所示:

const obj = {foo: 23};

// bar is not a type annotation here
const {foo: bar} = obj;

// 23
console.log(bar);

我不确定参数重新绑定在类型声明中有什么用处,但无论好坏,这就是它的意思。所以错误是因为 Merge<K, S> 不是重新绑定的有效标识符;但事实上你的 jsx2 和你的 jsx3 声明都有问题,只是你没有得到另一个的错误。

解决方案是将类型放在一个地方,在上下文中,它们实际上是类型;即在参数的类型注释中。

type Test<P, S=any, K=any> = {
    jsx1?: (state: Merge<K, S>, props: P, nextJsx?) => JSX.Element;
    jsx2?: (params: {state: S, props: P, nextJsx}) => JSX.Element;
    jsx3?: (params: {state: Merge<K, S>, props: P, nextJsx}) => JSX.Element;
}

请注意,该参数是一个名为 params 的对象,其类型现在出现在类型注释上下文中,因此不会被解析为重新绑定标识符。此外,尽管类型声明中只有一个命名参数 params,但在实际实现这些函数时仍然完全可以进行参数解构(如果需要,还可以重新绑定):

const test: Test<number, number, number> = {
    jsx2: ({state, props, nextJsx}) => console.log(state, props, nextJsx),
    jsx3: ({state, props, nextJsx}) => console.log(state, props, nextJsx),
};

Playground Link