For example, when I write:
type Email = string
type Password = string
const returnsEmail = (): Email => \'email@example.com\' as Email
const returnsPassw
Yes this is intended behaviour, type alias is called 'alias' precisely for that reason - it does not create a new distinct type.
Also, you probably will be surprised, but in TypeScript two different types are interchangeable if they have the same definition, it's called structural typing:
interface Person {
name: string;
}
interface Pet {
name: string;
}
const p: Pet = {name: 'Rosie'};
const person: Person = p; // no error
For the time being (until nominal types are added to TypeScript), one has to resort to various tricks to make types artificially incompatible. One such trick is called 'branded types' (example here), it works by adding superficial property to the type which is never used in the code, it serves only to make the type incompatible to anything else:
type Email = string & { __emailBrand: any };
type Password = string & { __passwordBrand: any };
const returnsEmail = (): Email => 'email@example.com' as Email
const returnsPassword = (): Password => 'P4ssw0rd' as Password
const email1: Email = 'email@example.com' as Email;//has to use type assertion here
const email2: Email = returnsEmail() // OK
const email3: Email = returnsPassword() // error