考虑到使用我自己的函数包装JSON.stringify的情况:
declare function stringify(
value: any,
replacer?: (key: string, value: any) => any,
space?: string | number
): string;
declare function stringify(
value: any,
replacer?: (number | string)[] | null,
space?: string | number
): string;
function myStringify(
data: object,
replacer: ((key: string, value: any) => any) | (number | string)[] | null,
space: string | number,
) {
return stringify(data, replacer, space); // TS error: type is compatible!
}
如何创建自己的方法myStringify重用JSON.stringify?
您可以通过TS playground
查看错误详情答案 0 :(得分:1)
问题是,由于replacer
是来自所有replacer
重载的stringify
参数类型的并集,因此它实际上与任何重载都不兼容。选择过载打字稿时会尝试找到最符合参数的重载,因为你的replacer
既不兼容第一次重载(过载需要一个函数,你的参数也可以是一个数组)或第二个重载(该重载需要一个数组,您的参数可以是一个函数)重载解析过程将失败。
您可以自己添加两个重载,或者您可以使用类型保护来实质上调用相同的函数,或者您可以只使用一个断言:
// assert to any
function myStringify(
data: object,
replacer: ((key: string, value: any) => any) | (number | string)[] | null,
space: string | number,
) {
return JSON.stringify(data, replacer as any, space)
}
// use a type gurad, but it seems overkill to do so.
function myStringify(
data: object,
replacer: ((key: string, value: any) => any) | (number | string)[] | null,
space: string | number,
) {
if(Array.isArray(replacer)) {
return JSON.stringify(data, replacer, space);
} else if(typeof replacer === "function") {
return JSON.stringify(data, replacer, space);
}
}
答案 1 :(得分:0)
受@Titian Cernicova-Dragomir的回答启发,我找到了一个通用的解决方案供参考。试试myFun2的做法。
declare function s(r: () => string): string;
declare function s(r: () => number): number;
const a = s(() => '123') // sring
const b = s(() => 123) // number
function myFun(r: (() => string) | (() => number)) {
type R = ReturnType<typeof r> extends string ? string : number
return s(r)// TS error: type is compatible!
}
const c = myFun(() => '123') // string, is decide by the order we declare the function 's'
const d = myFun(() => 123) // string, totally wrong
function myFun2(r: () => string): string;
function myFun2(r: () => number): number;
function myFun2(r: (() => string) | (() => number)): string | number {
type R = ReturnType<typeof r> extends string ? string : number
return s(r as any) as any as R
}
const e = myFun2(() => '123')
const f = myFun2(() => 123)