构造函数作为对象键
Constructors as object keys
我正在尝试构建类型和回调的映射,所以我从这样的结构开始:
type Instantiable<T = unknown> = new (...args: any[]) => T;
type SingleParamFn<TInput = unknown, TOuput = unknown> = (arg: TInput) => TOuput;
type TypesRecord<T> = { type: Instantiable<T>, callback: SingleParamFn<T> };
type TypesMap = TypesRecord[]; // This is the structure
这方面的一个例子:
const myMap: TypesMap = [{ type: Date, callback: (value) => 'this is a Date' }];
这似乎按预期工作,但我意识到它有点低效,因为您需要循环数组以找到您想要的类型。
我开始尝试将类型作为对象键,它似乎至少在 Google Chrome:
中有效
class MyFancyObject {}
class MyOtherObject {}
const map = {
[Date]: () => 'this is a date',
[MyFancyObject]: () => 'this is a fancy object',
[MyOtherObject]: () => 'this is another object'
};
console.log(map[Date]()); // 'this is a date'
console.log(map[MyFancyObject]()); // 'this is a fancy object'
console.log(map[MyOtherObject]()); // 'this is another object'
const obj = new MyFancyObject();
console.log(map[obj.constructor]()); // 'this is a fancy object'
console.log(map[(new Date()).constructor]()); // 'this is a date'
我一直在检查一些文档,似乎对象的键只能是 string or a Symbol so I checked what constitutes a Symbol and it seems to be a bit vage as it is defined as a built-in object whose constructor returns a symbol primitive that's guaranteed to be unique 并且对象的构造函数(据我所知)是唯一的。
鉴于所有这些,使用构造函数作为对象键是一种可靠的方法吗?如果是这样,我该如何定义此类对象的打字稿类型?如果不是,是否还有其他选项(例如 Map
对象)?
Given all of this, is using the constructors as object keys a reliable approach?
没有。如您所说,对象的键只能是字符串或Symbols。符号是从 Symbol
上的 属性(对于 well-known、specification-defined 符号)或通过调用 Symbol()
或 Symbol.for("...")
获得的原语。构造函数不是符号,它们是函数。
您的 map
对象的键是字符串。当您使用像 [MyFancyObject]
这样的计算 属性 名称时,如果您提供的值不是字符串或符号(在您的情况下,它是一个函数),它将隐式转换为字符串,就像您 String(MyFancyObject)
。你可以在这里看到:
class MyFancyObject {}
class MyOtherObject {}
const map = {
[Date]: () => 'this is a date',
[MyFancyObject]: () => 'this is a fancy object',
[MyOtherObject]: () => 'this is another object'
};
console.log(Object.keys(map));
console.log(map[MyFancyObject]()); // "this is a fancy object"
console.log(map["class MyFancyObject {}"]()); // also "this is a fancy object"
如您所见,您认为 MyFancyObject
的键实际上是字符串 "class MyFancyObject {}"
.
您 可以 使用构造函数作为 Map
中的键,但是:
class MyFancyObject {}
class MyOtherObject {}
const map = new Map([
[Date, () => 'this is a date'],
[MyFancyObject, () => 'this is a fancy object'],
[MyOtherObject, () => 'this is another object'],
]);
console.log(map.get(MyFancyObject)());
在那里,键实际上是构造函数,而不是从它们派生的字符串。
我正在尝试构建类型和回调的映射,所以我从这样的结构开始:
type Instantiable<T = unknown> = new (...args: any[]) => T;
type SingleParamFn<TInput = unknown, TOuput = unknown> = (arg: TInput) => TOuput;
type TypesRecord<T> = { type: Instantiable<T>, callback: SingleParamFn<T> };
type TypesMap = TypesRecord[]; // This is the structure
这方面的一个例子:
const myMap: TypesMap = [{ type: Date, callback: (value) => 'this is a Date' }];
这似乎按预期工作,但我意识到它有点低效,因为您需要循环数组以找到您想要的类型。
我开始尝试将类型作为对象键,它似乎至少在 Google Chrome:
中有效class MyFancyObject {}
class MyOtherObject {}
const map = {
[Date]: () => 'this is a date',
[MyFancyObject]: () => 'this is a fancy object',
[MyOtherObject]: () => 'this is another object'
};
console.log(map[Date]()); // 'this is a date'
console.log(map[MyFancyObject]()); // 'this is a fancy object'
console.log(map[MyOtherObject]()); // 'this is another object'
const obj = new MyFancyObject();
console.log(map[obj.constructor]()); // 'this is a fancy object'
console.log(map[(new Date()).constructor]()); // 'this is a date'
我一直在检查一些文档,似乎对象的键只能是 string or a Symbol so I checked what constitutes a Symbol and it seems to be a bit vage as it is defined as a built-in object whose constructor returns a symbol primitive that's guaranteed to be unique 并且对象的构造函数(据我所知)是唯一的。
鉴于所有这些,使用构造函数作为对象键是一种可靠的方法吗?如果是这样,我该如何定义此类对象的打字稿类型?如果不是,是否还有其他选项(例如 Map
对象)?
Given all of this, is using the constructors as object keys a reliable approach?
没有。如您所说,对象的键只能是字符串或Symbols。符号是从 Symbol
上的 属性(对于 well-known、specification-defined 符号)或通过调用 Symbol()
或 Symbol.for("...")
获得的原语。构造函数不是符号,它们是函数。
您的 map
对象的键是字符串。当您使用像 [MyFancyObject]
这样的计算 属性 名称时,如果您提供的值不是字符串或符号(在您的情况下,它是一个函数),它将隐式转换为字符串,就像您 String(MyFancyObject)
。你可以在这里看到:
class MyFancyObject {}
class MyOtherObject {}
const map = {
[Date]: () => 'this is a date',
[MyFancyObject]: () => 'this is a fancy object',
[MyOtherObject]: () => 'this is another object'
};
console.log(Object.keys(map));
console.log(map[MyFancyObject]()); // "this is a fancy object"
console.log(map["class MyFancyObject {}"]()); // also "this is a fancy object"
如您所见,您认为 MyFancyObject
的键实际上是字符串 "class MyFancyObject {}"
.
您 可以 使用构造函数作为 Map
中的键,但是:
class MyFancyObject {}
class MyOtherObject {}
const map = new Map([
[Date, () => 'this is a date'],
[MyFancyObject, () => 'this is a fancy object'],
[MyOtherObject, () => 'this is another object'],
]);
console.log(map.get(MyFancyObject)());
在那里,键实际上是构造函数,而不是从它们派生的字符串。