Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么typescript不允许在string | string[]类型中调用concat? 常量s:string='foo'; constpass1=(origin:string)=>origin.concat; constpass2=(origin:string[])=>origin.concat; 类型S=字符串|字符串[]; 常量错误=(原点:S)=>origin.concat;_Javascript_Typescript_Type Systems_Duck Typing - Fatal编程技术网

Javascript 为什么typescript不允许在string | string[]类型中调用concat? 常量s:string='foo'; constpass1=(origin:string)=>origin.concat; constpass2=(origin:string[])=>origin.concat; 类型S=字符串|字符串[]; 常量错误=(原点:S)=>origin.concat;

Javascript 为什么typescript不允许在string | string[]类型中调用concat? 常量s:string='foo'; constpass1=(origin:string)=>origin.concat; constpass2=(origin:string[])=>origin.concat; 类型S=字符串|字符串[]; 常量错误=(原点:S)=>origin.concat;,javascript,typescript,type-systems,duck-typing,Javascript,Typescript,Type Systems,Duck Typing,上面的代码。我可以在string或string[]类型中调用concat。那么为什么TypeScript不允许在string | string[]type中调用concat 错误是: Cannot invoke an expression whose type lacks a call signature. Type '((...strings: string[]) => string) | { (...items: ConcatArray<string>[]): string

上面的代码。我可以在
string
string[]
类型中调用
concat
。那么为什么TypeScript不允许在
string | string[]
type中调用
concat

错误是:

Cannot invoke an expression whose type lacks a call signature.
Type '((...strings: string[]) => string) | { (...items: ConcatArray<string>[]): string[]; (...items: (s...'
has no compatible call signatures.
无法调用其类型缺少调用签名的表达式。
键入“(…strings:string[])=>string){(…项:ConcatArray[]):string[];(…项:(s.)
没有兼容的呼叫签名。

因为它们有不同的返回类型?但我认为TS可以推断出
error
的类型是
s
。这是故意设计的吗?如果是,为什么?

因为虽然
concat
方法在这两种类型之间很常见,但在这两种类型之间有非常不同的签名,所以Typescript不能真正合并m的声明方法。虽然不理想,但您可以使用类型保护来区分这两种类型:

const s: string = 'foo';
type S = string | string[];

const error = (origin: S) => typeof origin === 'string' ?
    origin.concat(s) :
    origin.concat(s);
或者直接断言为
any

const s: string = 'foo';
type S = string | string[];

const error = (origin: S) =>  (origin as any).concat(s) as S
还可以选择将签名的并集转换为签名的交集。这在某些情况下可能很好,但在其他情况下则不行:

const s: string = 'foo';
type S = string | string[];

type UnionToIntersection<U> = 
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

function mergeSignature<T, K extends keyof T> (value: T, method: K) : UnionToIntersection<T[K]>{
    return ((...args: any[]) => (value[method] as any as Function).apply(value, args)) as any;
}

const error = (origin: S) => mergeSignature(origin, 'concat')(s); 
常量s:string='foo'; 类型S=字符串|字符串[]; 类型UnionToIntersection= (U扩展任何?(k:U)=>void:never)扩展((k:inferi)=>void)?I:never 函数mergeSignature(值:T,方法:K):UnionToIntersection{ 返回((…args:any[])=>(值[方法]作为任意函数)。应用(值,args))作为任意函数; } 常量错误=(原点:S)=>mergeSignature(原点“concat”)(S);
我更喜欢类型保护方式。谢谢。为什么在这种情况下TS不能合并结果类型?我可以编写一个函数,它可能返回
T1
T2
,但我不需要将函数返回类型显式声明为
T1 | T2
,TS可以推断出来。这里讨论了为什么他们不这样做,我想他们知道abo但毕竟,他们对这个问题发表了评论;)是的,在我在SOF中提出这个问题之前,我已经读过这个问题。我理解在联合类型中处理深度调用很困难,需要手工跟踪联合类型的组成,例如curry函数。但在我的情况下,这只是一个一级调用。这是一个设计权衡,但可以实现。对吗?@merito添加了一个新的解决方案,可以改变符号交叉点的签名联合使其可调用好消息是我们可以从TS 3.3中做到这一点。它还需要一些改进。例如,
const-ret=error('msg')
,ret的类型是什么?
ret
?TS推断它是
s
,但它应该是
string