Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript how to discriminate type aliases which refer to the same type

Tags:

typescript

For example, when I write:

type Email = string
type Password = string

const returnsEmail = (): Email => '[email protected]' as Email
const returnsPassword = (): Password => 'P4ssw0rd' as Password

const email1: Email = '[email protected]' // OK
const email2: Email = returnsEmail() // OK
const email3: Email = returnsPassword() // should not be OK but silent

TypeScript 2.8.3 seems to emit no errors here. Is this intended behaviour? TypeScript's "aliases" are just "macros"? I know TypeScript deals with only static typing and not validation (kinds of regex matching, in the case like above), but I think this is the bussiness for the former and should be done, especially if annotations explicitly written.

like image 215
yuhr Avatar asked May 11 '18 21:05

yuhr


1 Answers

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 protected]' as Email
const returnsPassword = (): Password => 'P4ssw0rd' as Password

const email1: Email = '[email protected]' as Email;//has to use type assertion here
const email2: Email = returnsEmail() // OK
const email3: Email = returnsPassword() // error
like image 53
artem Avatar answered Oct 06 '22 21:10

artem