我不确定为什么我们需要 ExtractInstanceType 以及为什么我们不想只使用 IStaff?
因为整个要点userMap
关联的静态方法是将名称映射到具体的,具体的类,而不是它们实现的接口。如果这些类中的任何一个在通用 IStaff 接口之上实现了特定于类的内容(而且几乎肯定会),那么您的代码将充斥着instanceof
或每次调用不在其中的方法时进行其他检查IStaff
如果您没有通过使用该静态方法缩小类型来满足编译器的要求,从而将其消灭在萌芽状态。
我以为这只是 userMap 可以保存的字典中的键之一,这将是一个字符串?
正如我在对您的回答的评论中所建议的其他问题 https://stackoverflow.com/questions/69690959/creating-a-factory-in-typescript-using-infer-and-typeof我认为问题在于你仍然混为一谈types and values。 TBF 存在一些重叠并没有帮助。
考虑字符串“a”。在 Typescript 中,有value'a' 但也有文字类型 'a',它是类型的子集string
:
type a = 'a'
let a: a = 'a'
let s: string = a // note, variable a not string literal a!
const foo = {
a: 1
}
console.log(foo[a]) // 1
console.log(foo[s]) // type error!
// ok, let's try the string literal 'a'
s = 'a'
console.log(foo[s]) // same type error!
// eff
Since a
字面上是“a”,我们可以索引foo
用它。但s
是一个到字符串的可变绑定,并且你不能索引foo
即使我们设置了任何旧字符串value到“a”,即使我们将其设置为variable a
其中有type a, s
is still a string编译器无法保证我们不会重新分配非 a 值。操场 https://www.typescriptlang.org/play?#code/C4TwDgpgBAhlC8UDkMkCgA2FiwFywWVU2ygGd8zgAnASwDsBzQmNAYwHt6qoAzDjoQDeaKHigBGNAF807LmQ5YAdBg6MAFPw4BtGAF0AlPO5KIq9VoE6yRtEA
类型可能看起来像值,并且在某些上下文中可能具有完全相同的值外貌作为价值观,但它们是not值,也不是值类型。继续往右走...
对于对象字面量,我们在编译时知道对象中的键,因此如果我们有一个 foo 对象{a: 'hi', b: 5}
then keyof typeof foo
is 'a' | 'b'
。注意:这些是字符串,但在本例中它们是types,不是 JavaScriptvalues。博客文章中的方法限制了k
参数只能传递为编译时已知键中的值userMap
.
但是,当使用该方法时,它是否与对象实例一起用作其参数,还是不可能?
哦,这是possible改变方法以这种方式工作,这是毫无意义的。如果您有一个实例的引用,那么您已经有一个对其构造函数的引用,您不需要查找表来创建另一个实例:
class Foo {}
const foo = new Foo()
const bar = new (foo.constructor as any)()
bar instanceof Foo // true
再次强调一下重点userMap
访问它的静态方法是为了让工厂能够通过以下方式查找正确的用户类字符串名称.