当试图将值作为泛型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
?
TypeScript 4.4.4。
TS游乐场:
游乐场
在签名中,({state: S, props: P, nextJsx}) => JSX.Element
、S
和P
不是类型,而是标识符。在这种情况下,冒号:
并不意味着类型注释,它意味着重新绑定属性的名称,如以下示例所示:
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),
};
游乐场链接
您在jsx2
和jsx3
中使用不同的名称来销毁对象,而不是键入它们。在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;
};