扩展字符串的 TypeScript 新 class
TypeScript new class that extends String
我目前正在尝试设置 class "AdvancedString"。这个 class 应该通过像这样的方法扩展 String是JSON。目前看起来像这样
class AdvancedString extends String {
isJSON():boolean{
var itIs = true;
try{
JSON.parse(this.toString());
} catch (err) {
itIs = false;
}
return itIs;
}
}
export{ AdvancedString}
现在效果还不错。如果我用 "SampleString" 创建一个新实例,我会得到
let sample = new AdvancedString("SampleString");
// ExtendedString {[[PrimitiveValue]]: "SampleString"}
如果我执行 toString,我会得到正确的值
sample.toString()
// "SampleString"
但是当我直接调用它时,我希望它表现得像普通字符串一样
sample === "SampleString"
// should return true and sample.toString() === "SampleString"
// should not be necessary
有没有什么方法可以在 TypeScript 中完成,或者这是不可能的?我想使用一个单独的 class 而不是将我的方法添加到 string
的原型中
不幸的是,这是不可能的。对象仍然是对象,不是 ===
原始值(字符串)。
相信我,我已经在这个问题上花了几十个小时,你根本无能为力。
你可以变异 String.prototype.isJSON
String.prototype.isJson = () => 'your logic here'
但这不是一个非常干净的解决方案,除非您确定此代码仅保留在您的应用程序中。
P.S。打字稿与此问题无关。
===
要求类型相同。 AdvancedString
类型的实例与原始字符串或对象字符串的类型不同,因此 ===
始终为假。 new String("") === ""
也是假的,同理;前者是String对象,后者是原始字符串
您的 AdvancedString
是 ==
原始字符串,但(看起来)仅当您本机使用 class
时;当我 try that in the TypeScript playground 使用 TypeScript 转译 class
语法时,它失败了。但它本机工作:
class AdvancedString extends String {
isJSON() {
var itIs = true;
try {
JSON.parse(this.toString());
} catch (err) {
itIs = false;
}
return itIs;
}
}
const s = new AdvancedString("foo");
console.log(s === "foo"); // false
console.log(s == "foo"); // true
但是,您可能需要考虑使用 AdvancedString
的缺点,因为您的字符串将是对象,而不是基元:
- 内存影响。分配这些字符串对象比使用原始字符串对内存的影响更大。¹
- 任何接收您的字符串之一(例如,您可能正在使用的库)并执行
typeof
检查的代码都不会将它们视为(原始)字符串。因此,例如,接受字符串或选项对象的 API 如果将 AdvancedString
实例传递给它,则可能会被误导。发生这种情况时,TypeScript 可能无法警告您,具体取决于库的注释方式(string|object
,例如,不会捕捉到它)。
¹ 出于好奇,我这样做了:
const s = "**y";
const a = Array.from({length: 100000}, () => new String("x" * s));
...在空白页上。我最终在内存中有 100,005 String
个实例(我猜有 5 个来自其他地方)占用 3,200,160 字节。相比之下,这个:
const s = "**y";
const a = Array.from({length: 100000}, () => "x" + s);
...仅将原始字符串的数量从 3,830(281,384 字节)增加到 27,533(1,040,120 字节);显然其中一些(但不是全部)被重复使用。
因此,原语约为 741kB,而对象约为 3MB,是内存的四倍多一点。
这只是一项综合测试,但您明白了。
我目前正在尝试设置 class "AdvancedString"。这个 class 应该通过像这样的方法扩展 String是JSON。目前看起来像这样
class AdvancedString extends String {
isJSON():boolean{
var itIs = true;
try{
JSON.parse(this.toString());
} catch (err) {
itIs = false;
}
return itIs;
}
}
export{ AdvancedString}
现在效果还不错。如果我用 "SampleString" 创建一个新实例,我会得到
let sample = new AdvancedString("SampleString");
// ExtendedString {[[PrimitiveValue]]: "SampleString"}
如果我执行 toString,我会得到正确的值
sample.toString()
// "SampleString"
但是当我直接调用它时,我希望它表现得像普通字符串一样
sample === "SampleString"
// should return true and sample.toString() === "SampleString"
// should not be necessary
有没有什么方法可以在 TypeScript 中完成,或者这是不可能的?我想使用一个单独的 class 而不是将我的方法添加到 string
的原型中不幸的是,这是不可能的。对象仍然是对象,不是 ===
原始值(字符串)。
相信我,我已经在这个问题上花了几十个小时,你根本无能为力。
你可以变异 String.prototype.isJSON
String.prototype.isJson = () => 'your logic here'
但这不是一个非常干净的解决方案,除非您确定此代码仅保留在您的应用程序中。
P.S。打字稿与此问题无关。
===
要求类型相同。 AdvancedString
类型的实例与原始字符串或对象字符串的类型不同,因此 ===
始终为假。 new String("") === ""
也是假的,同理;前者是String对象,后者是原始字符串
您的 AdvancedString
是 ==
原始字符串,但(看起来)仅当您本机使用 class
时;当我 try that in the TypeScript playground 使用 TypeScript 转译 class
语法时,它失败了。但它本机工作:
class AdvancedString extends String {
isJSON() {
var itIs = true;
try {
JSON.parse(this.toString());
} catch (err) {
itIs = false;
}
return itIs;
}
}
const s = new AdvancedString("foo");
console.log(s === "foo"); // false
console.log(s == "foo"); // true
但是,您可能需要考虑使用 AdvancedString
的缺点,因为您的字符串将是对象,而不是基元:
- 内存影响。分配这些字符串对象比使用原始字符串对内存的影响更大。¹
- 任何接收您的字符串之一(例如,您可能正在使用的库)并执行
typeof
检查的代码都不会将它们视为(原始)字符串。因此,例如,接受字符串或选项对象的 API 如果将AdvancedString
实例传递给它,则可能会被误导。发生这种情况时,TypeScript 可能无法警告您,具体取决于库的注释方式(string|object
,例如,不会捕捉到它)。
¹ 出于好奇,我这样做了:
const s = "**y";
const a = Array.from({length: 100000}, () => new String("x" * s));
...在空白页上。我最终在内存中有 100,005 String
个实例(我猜有 5 个来自其他地方)占用 3,200,160 字节。相比之下,这个:
const s = "**y";
const a = Array.from({length: 100000}, () => "x" + s);
...仅将原始字符串的数量从 3,830(281,384 字节)增加到 27,533(1,040,120 字节);显然其中一些(但不是全部)被重复使用。
因此,原语约为 741kB,而对象约为 3MB,是内存的四倍多一点。
这只是一项综合测试,但您明白了。