如何编写正在接受类型检查的 TypeScript 原始类型扩展方法
How to write a TypeScript primitive type extension method that is being type-checked
在 TypeScript 中,我想以这种方式向原始类型添加扩展方法,以便在转译时对参数和 return 类型进行类型检查。
然而,到目前为止,我还没有成功。我发现了很多关于这个主题的有用线索,其中 none 提供了解决方案。由于我发现的都已经过时了,我想再次提出这个话题。
这是我到目前为止尝试过的:
declare global {
interface String {
myCoolMethod(inputValue: number): string;
}
}
String.prototype.myCoolMethod = function (inputValue: number): string {
return this + inputValue.toString();
};
同样的方式不同:
Object.defineProperty(String.prototype, "myCoolMethod", {
value: function myCoolMethod(inputValue: number) : string {
return this + inputValue.toString();
},
writable: true,
configurable: true
}
);
这些片段有效,但在转译时没有类型检查,在 (Visual Studio) 编辑器中没有智能感知警告。我在 VS2019 上使用 TypeScript 3.7。
是否有(现在)在 TypeScript 中结合类型检查和扩展方法的方法?
更新:
请参阅下面我的回答,其中我指出了真正的问题(对我自己,以及任何可能受益的人...)
在 index.d.ts
文件(或您的根类型文件)中声明接口的扩展:
interface String {
myCoolMethod(input: number): string;
}
然后用方法实现创建一个单独的文件:
// strProto.ext.ts
String.prototype.myCoolMethod = function (inputValue: number): string {
return this + inputValue.toString();
};
并导入该文件:
import '../types/strProto.ext'
这应该也能让您访问具有类型安全性的方法。在 VSCode.
中的 TS 3.7 上测试
我正在回答我自己的问题,所以我可以将其标记为已解决:
这个问题与我最初想象的完全不同。正如 jcalz 指出的那样,这确实给了我一个类型错误,正如预期的那样:
const s = "hello";
console.log(s.myCoolMethod(123)); // hello123
s.myCoolMethod("oops"); // error, not a number
但是在我的消费代码中,我有这个,没有给我一个错误:
somebodysPackage.somebodysFunction().join(", ").myCoolMethod("oops"); // no error
尽管 Javascript 函数 join() 总是 returns 一个字符串,但 TypeScript 没有找到我的 String 扩展方法,尽管它在运行时被 Javascript 正确执行。
然而,将 somebodysFunction 的结果转换为 string[] 会改变:
(somebodysPackage.somebodysFunction()) as string[]).join(", ").myCoolMethod("oops"); // type error
现在,TypeScript 知道 join() 的输入类型并且可以推断出输出类型并且我的扩展函数被正确定位并抛出类型错误。
最后,从 npm 安装 somebodysPackage
的类型声明文件解决了没有显式转换的问题。
在 TypeScript 中,我想以这种方式向原始类型添加扩展方法,以便在转译时对参数和 return 类型进行类型检查。
然而,到目前为止,我还没有成功。我发现了很多关于这个主题的有用线索,其中 none 提供了解决方案。由于我发现的都已经过时了,我想再次提出这个话题。
这是我到目前为止尝试过的:
declare global {
interface String {
myCoolMethod(inputValue: number): string;
}
}
String.prototype.myCoolMethod = function (inputValue: number): string {
return this + inputValue.toString();
};
同样的方式不同:
Object.defineProperty(String.prototype, "myCoolMethod", {
value: function myCoolMethod(inputValue: number) : string {
return this + inputValue.toString();
},
writable: true,
configurable: true
}
);
这些片段有效,但在转译时没有类型检查,在 (Visual Studio) 编辑器中没有智能感知警告。我在 VS2019 上使用 TypeScript 3.7。
是否有(现在)在 TypeScript 中结合类型检查和扩展方法的方法?
更新:
请参阅下面我的回答,其中我指出了真正的问题(对我自己,以及任何可能受益的人...)
在 index.d.ts
文件(或您的根类型文件)中声明接口的扩展:
interface String {
myCoolMethod(input: number): string;
}
然后用方法实现创建一个单独的文件:
// strProto.ext.ts
String.prototype.myCoolMethod = function (inputValue: number): string {
return this + inputValue.toString();
};
并导入该文件:
import '../types/strProto.ext'
这应该也能让您访问具有类型安全性的方法。在 VSCode.
中的 TS 3.7 上测试我正在回答我自己的问题,所以我可以将其标记为已解决:
这个问题与我最初想象的完全不同。正如 jcalz 指出的那样,这确实给了我一个类型错误,正如预期的那样:
const s = "hello";
console.log(s.myCoolMethod(123)); // hello123
s.myCoolMethod("oops"); // error, not a number
但是在我的消费代码中,我有这个,没有给我一个错误:
somebodysPackage.somebodysFunction().join(", ").myCoolMethod("oops"); // no error
尽管 Javascript 函数 join() 总是 returns 一个字符串,但 TypeScript 没有找到我的 String 扩展方法,尽管它在运行时被 Javascript 正确执行。
然而,将 somebodysFunction 的结果转换为 string[] 会改变:
(somebodysPackage.somebodysFunction()) as string[]).join(", ").myCoolMethod("oops"); // type error
现在,TypeScript 知道 join() 的输入类型并且可以推断出输出类型并且我的扩展函数被正确定位并抛出类型错误。
最后,从 npm 安装 somebodysPackage
的类型声明文件解决了没有显式转换的问题。