TypeScrip: Oh, that funny type system

Hello, my name is Dmitry Karlovsky and recently I, together with Artur Mukminov , held a workshop where I showed how to develop complex typofunctions through testing . This is 2 hours of harsh type programming. So as a teaser, catch an analysis of the curiosities of the typescript type system.













Relationships are hard



It is very easy to check if one type is a subtype of another using the typoternary:







type IsAExtendsB = A extends B ? true : false
      
      





Classify, 2 4 :







  • [ A, '<:', B ]



    β€” A B.
  • [ A, ':>', B ]



    β€” B A.
  • [ A, '==', B ]



    β€” ( ).
  • [ A, '!=', B ]



    β€” .


, Equal Assert, , , . Assert , .







! ..



β€” Object



object



β€” , , :







type boolean_is_Object = Assert<
    boolean extends Object ? true : false,
    true
>

type boolean_is_not_object = Assert<
    boolean extends object ? true : false,
    false
>
      
      





, , , :







type Object_vs_object = Assert<
    Classify< Object, object >,
    [ Object, '==', object ]
>
      
      





: (, boolean



) (, Object



), β€” (, object



), β€” .







, . Object



, object



.









, , β€” , :







type boolean_is_true_or_false = Assert<
    boolean,
    true | false
>
      
      





:







enum FL4 { Absurd, False, True, Unknown }

type FL4_is_union = Assert<
    FL4,
    | FL4.Absurd | FL4.False | FL4.True | FL4.Unknown
>
      
      





( ):







type Absurd_is_number = Assert<
    Classify< FL4.Absurd, number >,
    [ FL4.Absurd, '==', number ]
>
      
      





:







type Absurd_is_never_wtf = Assert<
    Classify< FL4.Absurd, 0 >,
    [ never, '<:', 0 ]
>
      
      





, , ? , !







type One_is_never_wtf = Assert<
    Classify< FL4.Absurd, 1 >,
    [ FL4.Absurd, ':>', never ]
>
      
      





, , !







, β€” , :







enum FL3 { Absurd, False, True }

type Absurd_is_not_Absurd = Assert<
    Equal< FL3.Absurd, FL4.Absurd > | false,
    false
>
      
      





, . , , , :







enum HappyDebugging {
    False = "True", 
    True = "False",
}

type True_extends_string = Assert<
    Classify< HappyDebugging.True, string >,
    [ HappyDebugging.True, '<:', string ]
>
      
      





, number



, string



.









, :







  • never



    . , .
  • unknown



    β€” . . unknown



    .


But what is it looming next to them? Yes it is any



!
On the one hand, it is completely interchangeable with unknown



:







type unknown_is_any = Assert<
    unknown,
    any
>
      
      





But on the other hand, like SchrΓΆdinger's cat, it is a subtype never



(and as a consequence, of any other type of do unknown



) and is not such at the same time:







type any_maybe_extends_never = Assert<
    any extends never ? true : false,
    true | false
>
      
      





In short, it any



breaks through the bottom in every possible sense. The fate of those who come face to face with him is hard ...













All the code from the article.







Happy debugging guys!














All Articles