微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么打字稿不允许在字符串中调用concat | Javascript字符串[]类型?

const s: string = 'foo';

const pass1 = (origin: string) => origin.concat(s);
const pass2 = (origin: string[]) => origin.concat(s);

type S = string | string[];

const error = (origin: S) => origin.concat(s);

上面的代码.我可以用字符串或string []类型调用concat.那么,为什么TypeScript不允许在字符串中调用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.

因为他们有不同的返回类型?但是我认为TS可以推断错误的类型是S.这是故意设计吗?如果是,为什么?

解决方法:

因为concat方法在这两种类型之间是公用的,但在两者之间却具有非常不同的签名,因此Typescript不能真正合并这些方法的声明.虽然不理想,但是可以使用类型保护来区分这两种类型:

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

const error = (origin: S) => typeof origin === 'string' ?
    origin.concat(s) :
    origin.concat(s);

或者只是断言为:

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); 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐