Reputation: 1172
Let's say I have two or more type aliases, as such:
declare type A = string;
declare type B = string;
I have variables of these types, as well as functions that operate on them.
const a1: A = "example of a";
const b1: B = "example of b";
function withA(a: A){
console.log(a);
}
function withB(b: B){
console.log(b);
}
I would like the following code to error, but it does not:
withA(b1);
withB(a1);
How can I accomplish this? I will also need to be able to initialize the variables with a string (I'm assuming with a cast). However, once initialized I do not want the types to be "implicitly equivalent" and want to have the compiler forbid their interchangeable use.
I also would like to not have to use classes, as described here: TypeScript - specific string types
Upvotes: 12
Views: 1903
Reputation: 249536
Type aliases as their name suggests don't add anything to the type they alias. So as far as TS is concerned both A
and B
are the same type namely string
.
What you can do is use branded types. This is a technique where you take the base type (string
in this case) and intersect it with an object type with a property so as to make the type structurally incompatible with anything else from the compiler's point of view with. The property does not need to exist at runtime, it is just there as a marker for the compiler:
type A = string & { __brand: "A"};
type B = string & { __brand: "B"};
const a1: A = makeA("example of a");
const b1: B = makeB("example of b");
function makeA(s: string) {
return s as A
}
function makeB(s: string) {
return s as B
}
function withA(a: A){
console.log(a);
}
function withB(b: B){
console.log(b);
}
withA(b1); // error
withB(a1); // error
The utility functions makeA
and makeB
are not strictly necessary, you can just use a type assertion when you assign the string
, but they make the DX better.
Note: There are two proposals for formalizing this technique in the type system (Structural tag type
brands and Nominal unique type
brands ) but neither is merged at the time of writing, maybe in a future TS version we will get one of these.
Upvotes: 17