TypeScript is often referred as a structural typing language, the one whose type checking system takes into account only the (mis)match of the members (properties) of value to the target type.
In this regard, how TypeScript actually and structurally defines the primitive types, such as string
or number
? Are there interfaces declared that include all the needed properties? (charaAt
, concat
, and so on for strings. toExponential
, valueOf
, and so on for numbers)
Still, it's not to easy to me to tell what the structural error prevents assignments in cases like this:
type AB = 'A' | 'B';
const c: AB = 'C'; // Type '"C"' is not assignable to type 'AB'.
What properties does not have 'C'
which present on 'A'
or 'B'
?
Answers
In TypeScript, primitive types like string
and number
are indeed structurally typed, but they are built-in types that are implicitly understood by the TypeScript compiler. Their definitions and constraints are enforced by the compiler itself rather than through explicit interfaces.
When you define a variable with a primitive type, such as string
or number
, TypeScript expects the value assigned to that variable to conform to the structure and behavior associated with that primitive type. For example:
let str: string = 'hello';
let num: number = 42;
In the case of 'A' | 'B'
, it represents a union type where the variable c
can be either 'A'
or 'B'
. When you attempt to assign 'C'
to c
, TypeScript detects that 'C'
is not compatible with either 'A'
or 'B'
, thus it throws a type error. This is because 'C'
does not have the properties or characteristics of either 'A'
or 'B'
.
To answer your question specifically about what properties 'C'
lacks that are present in 'A'
or 'B'
, in this context, it's not about properties in the traditional sense like you would find in an object. Instead, it's about the specific values that are allowed in a union type. In this case, the union type 'A' | 'B'
explicitly states that the value can only be either 'A'
or 'B'
, and anything else is considered incompatible.
You can think of it as a constraint enforced by TypeScript: when you declare a variable with a union type, only the specified values in the union are allowed, and any other value will result in a type error. This is one of the ways TypeScript helps catch potential errors at compile time.