Issue
I can not get it why TypeScript has different suggestions for equal types (ObjType1 and ObjType2)?
In the first case it has a union type "a" | "b"
In the second case for the same type it didn't provide a union type. Why?
const obj = {
a: 1,
b: 1,
};
type ObjType1 = {
a: number;
b: number;
}
type ObjType2 = typeof obj;
type R1 = ObjType1 extends ObjType2 ? true : false; // true
type R2 = ObjType2 extends ObjType1 ? true : false; // true
type Result1 = keyof ObjType2; // type Result1 = "a" | "b"
type Result2 = keyof ObjType1; // type Result2 = keyof ObjType1
Solution
"a" | "b"
and keyof ObjType1
are exactly the same type in that code.
In the second case for the same type it didn't provide a union type.
keyof ObjType1
is a union type. It's just a different name¹ for "a" | "b"
. They mean the same thing and are interchangeable (until or unless you change the definition of ObjType1
or obj
).
The only difference here is the name for the type that TypeScript uses for display purposes (for instance, what it reports to the IDE via the language server process). But TypeScript's type system almost never cares about names/labels/aliases (an exception is declaration merging for interfaces). The type system is structural; it cares about the shape of types, not what they're called.
As to why TypeScript chooses the name/label/whatever keyof ObjType1
over "a" | "b"
in the second case, I suspect it's because it provides more useful information — it tells you were the type's meaning comes from. (Granted, keyof typeof obj
in the first example would also provide more information than just "a" | "b"
, but then you'd have to know that obj
is a runtime identifier, not a type.)
¹ Or perhaps I should call it label? I don't think alias quite applies here...
Answered By - T.J. Crowder
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.