Skip to content

Instantly share code, notes, and snippets.

@ruizb
Last active January 17, 2025 13:06
Show Gist options
  • Select an option

  • Save ruizb/55e1fc37cb198dccfdaf81450c3ebd43 to your computer and use it in GitHub Desktop.

Select an option

Save ruizb/55e1fc37cb198dccfdaf81450c3ebd43 to your computer and use it in GitHub Desktop.

Revisions

  1. ruizb revised this gist Mar 28, 2021. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,14 @@ Disclaimer: it was me, I was the developer that struggled. I still struggle thou

    You may not agree with some definitions or examples in this document. Please, feel free to leave a comment and let me know, only together can we improve this glossary! Also, if the stars are aligned and this _gist_ gets more and more attention, I might move it into its own repository so we can all contribute via issues and pull-requests! :rocket:

    ---

    ## UPDATE 2021-03-28

    I decided to create a GitHub repository: [ruizb/glossary-typescript](https://github.com/ruizb/glossary-typescript). This gist will not be updated anymore, please refer to the repository instead! :slightly_smiling_face:

    ---

    ## Table of content

    - [Ambient declaration](#ambient-declaration)
  2. ruizb revised this gist Oct 23, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -322,9 +322,9 @@ You can go to the [official documentation](https://www.typescriptlang.org/docs/h
    ### Type assertion
    [Type assertions](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions), frequently named _type casting_ wrongly, let you tell the compiler "trust me, I know a type more suitable for this value than the one you inferred". Contrary to casting, assertions don't change the structure of the value, they don't have any impact at runtime. The language assumes you did the runtime checks before using a type assertion, so it's your responsibility to make sure a value has the correct type when using an assertion.
    [Type assertions](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions), frequently named _type casting_ wrongly, let you tell the compiler "trust me, I know a type more suitable for this value than the one you inferred". Contrary to casting in other languages, assertions don't change the structure of the value, they don't have any impact at runtime. The language assumes you did the runtime checks before using a type assertion, so it's your responsibility to make sure a value has the correct type when using an assertion.
    There are 2 ways to use a type assertion, either by using the `as X` or `<X>` keywords.
    There are 2 ways to use a type assertion, either by using the `as X` keyword, or `<X>` syntax.
    ##### Example
    ```ts
  3. ruizb revised this gist Oct 23, 2020. 1 changed file with 28 additions and 0 deletions.
    28 changes: 28 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    - [Type alias](#type-alias)
    - [Type assertion](#type-assertion)
    - [Type check](#type-check)
    - [Type guard](#type-guard)
    - [Type inference](#type-inference)
    @@ -319,6 +320,33 @@ type Predicate_2<A> = (value: A) => boolean
    You can go to the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases) regarding type aliases for more information.
    ### Type assertion
    [Type assertions](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions), frequently named _type casting_ wrongly, let you tell the compiler "trust me, I know a type more suitable for this value than the one you inferred". Contrary to casting, assertions don't change the structure of the value, they don't have any impact at runtime. The language assumes you did the runtime checks before using a type assertion, so it's your responsibility to make sure a value has the correct type when using an assertion.
    There are 2 ways to use a type assertion, either by using the `as X` or `<X>` keywords.
    ##### Example
    ```ts
    const name: unknown = 'Bob'

    const strLength = (name as string).length
    // or
    const altStrLength = (<string>name).length
    ```

    Bear in mind that, if the type inferred by TypeScript and your type assertion don't overlap, then the compiler will raise an error. To avoid this, either the type assertion must be a subtype of the type inferred by TypeScript, or the other way around.

    ```ts
    const value = 42 // inferred as `number`

    const res = (value as string).length
    /** TS error 2352 on `value as string`:
    * Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other.
    * If this was intentional, convert the expression to 'unknown' first.
    */
    ```

    ### Type check

    Type checking is one of the features available with the TypeScript language. The type checker verifies the semantics of the types of your project to make sure the program is "correct" type-wise. Other features included in TypeScript are code parsing, code transformations (TS/JS => JS), language service for tools that allow e.g. [IntelliSense](#intellisense).
  4. ruizb revised this gist Oct 22, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ You may not agree with some definitions or examples in this document. Please, fe

    ### Ambient declaration

    An ambient declaration lets you tell the compiler of an existing variable/function: "I know you can't find it but trust me, this variable/function exists at runtime, and it has this type". The `declare` keyword lets you write such declaration.
    An ambient declaration lets you tell the compiler that a global variable/function exists, and which type it has: "I know you can't find it but trust me, this variable/function exists at runtime, and it has this type". The `declare` keyword lets you write such declaration.

    ##### Example
    ```ts
  5. ruizb revised this gist Oct 22, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ Disclaimer: it was me, I was the developer that struggled. I still struggle thou

    You may not agree with some definitions or examples in this document. Please, feel free to leave a comment and let me know, only together can we improve this glossary! Also, if the stars are aligned and this _gist_ gets more and more attention, I might move it into its own repository so we can all contribute via issues and pull-requests! :rocket:

    ## Table on content
    ## Table of content

    - [Ambient declaration](#ambient-declaration)
    - [Conditional type](#conditional-type)
  6. ruizb revised this gist Sep 26, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -170,7 +170,7 @@ For `B`, its type results in `{ name: never, age: number, adult: boolean }` beca
    An intrinsic type is a type which implementation is provided by the TypeScript compiler. It's a type that cannot be expressed by any feature provided by the type system of the language.
    It was first introduced [in this PR](https://github.com/microsoft/TypeScript/pull/40580) by a TypeScript maintainer. This PR adds 4 intrinsic string types to TypeScript:
    It was first introduced [in this PR](https://github.com/microsoft/TypeScript/pull/40580) by a TypeScript maintainer for the v4.1 release. This PR adds 4 intrinsic string types to TypeScript:
    ```ts
    type Uppercase<S extends string> = intrinsic;
  7. ruizb revised this gist Sep 25, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -172,7 +172,7 @@ An intrinsic type is a type which implementation is provided by the TypeScript c
    It was first introduced [in this PR](https://github.com/microsoft/TypeScript/pull/40580) by a TypeScript maintainer. This PR adds 4 intrinsic string types to TypeScript:
    ```t
    ```ts
    type Uppercase<S extends string> = intrinsic;
    type Lowercase<S extends string> = intrinsic;
    type Capitalize<S extends string> = intrinsic;
  8. ruizb revised this gist Sep 25, 2020. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Discriminated union](#discriminated-union)
    - [IntelliSense](#intellisense)
    - [Intersection type](#intersection-type)
    - [Intrinsic type](#intrinsic-type)
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    - [Type alias](#type-alias)
    @@ -165,6 +166,21 @@ Here, `A` is `never`, because the [string literals](#literal-type) `'a'` and `'b
    For `B`, its type results in `{ name: never, age: number, adult: boolean }` because `string` and `number` have nothing in common. As one of its properties type is `never`, there's no way to create a value which type is `B`, because no value can be assigned to the `never` type.
    ### Intrinsic type
    An intrinsic type is a type which implementation is provided by the TypeScript compiler. It's a type that cannot be expressed by any feature provided by the type system of the language.
    It was first introduced [in this PR](https://github.com/microsoft/TypeScript/pull/40580) by a TypeScript maintainer. This PR adds 4 intrinsic string types to TypeScript:
    ```t
    type Uppercase<S extends string> = intrinsic;
    type Lowercase<S extends string> = intrinsic;
    type Capitalize<S extends string> = intrinsic;
    type Uncapitalize<S extends string> = intrinsic;
    ```

    More intrinsic types could be added in the future.

    ### Literal type

    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".
  9. ruizb revised this gist Jul 24, 2020. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,7 @@ You may not agree with some definitions or examples in this document. Please, fe

    ## Table on content

    - [Ambient declaration](#ambient-declaration)
    - [Conditional type](#conditional-type)
    - [Diagnostic message](#diagnostic-message)
    - [Discriminated union](#discriminated-union)
    @@ -29,6 +30,22 @@ You may not agree with some definitions or examples in this document. Please, fe

    ## Glossary

    ### Ambient declaration

    An ambient declaration lets you tell the compiler of an existing variable/function: "I know you can't find it but trust me, this variable/function exists at runtime, and it has this type". The `declare` keyword lets you write such declaration.

    ##### Example
    ```ts
    doSomething(42) // TS error, "Cannot find name 'doSomething'"
    ```

    ```ts
    // no implementation is provided here, because it's available at runtime.
    declare function doSomething(n: number): void

    doSomething(42) // no TS error
    ```

    ### Conditional type

    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform type mapping_, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.
  10. ruizb revised this gist Jul 10, 2020. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -300,7 +300,11 @@ Here, the type checker tells us there is an error for the type of `name`: `Type

    ### Type guard

    A type guard, whether it's built into the TypeScript language or provided by the developer via a [type predicate](#type-predicate), allows for a type to be [narrowed](#type-narrowing) and guaranteed in a conditional branch.
    > "A type guard is some expression that performs a runtime check that guarantees the type in some scope."
    >
    > - From the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards).
    We can use the `typeof` operator or a [type predicate](#type-predicate) to enable _type guards_. It also allows for a type to be [narrowed](#type-narrowing) in a conditional branch.

    ##### Example
    ```ts
    @@ -323,8 +327,6 @@ By checking the type of `value` with `typeof`, TypeScript knows that in the `if`
    - In the `if (typeof value === 'number') { ... }` branch, `value` type is narrowed from `string | number` to `number`.
    - In the `else { ... }` branch, since all the possible types have been checked in the previous `if` conditions, `value` type is narrowed from `string | number` to `never` (it "can't" happen since all the possible cases have been checked already).

    You can also check the official [documentation about type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types).

    ### Type inference

    Type inference is the ability for the TypeScript compiler to appropriately _guess_ the type of a value, without manually specifying the type for that value.
  11. ruizb revised this gist Jul 10, 2020. 1 changed file with 37 additions and 32 deletions.
    69 changes: 37 additions & 32 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -24,6 +24,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Type guard](#type-guard)
    - [Type inference](#type-inference)
    - [Type narrowing](#type-narrowing)
    - [Type predicate](#type-predicate)
    - [Union type](#union-type)

    ## Glossary
    @@ -299,7 +300,7 @@ Here, the type checker tells us there is an error for the type of `name`: `Type

    ### Type guard

    A type guard, whether it's built into the TypeScript language or provided by the developer, allows for a type to be [narrowed](#type-narrowing) in a conditional branch.
    A type guard, whether it's built into the TypeScript language or provided by the developer via a [type predicate](#type-predicate), allows for a type to be [narrowed](#type-narrowing) and guaranteed in a conditional branch.

    ##### Example
    ```ts
    @@ -322,37 +323,6 @@ By checking the type of `value` with `typeof`, TypeScript knows that in the `if`
    - In the `if (typeof value === 'number') { ... }` branch, `value` type is narrowed from `string | number` to `number`.
    - In the `else { ... }` branch, since all the possible types have been checked in the previous `if` conditions, `value` type is narrowed from `string | number` to `never` (it "can't" happen since all the possible cases have been checked already).

    The developer can also create its own type guards thanks to the `is` syntax.

    ##### Example
    ```ts
    interface User {
    name: string
    age: number
    }

    // You can ignore this function for the sake of this example
    const hasOwnProperty = <A extends {}, B extends PropertyKey>(obj: A, prop: B): obj is A & Record<B, unknown> =>
    obj.hasOwnProperty(prop)

    const isUser = (v: unknown): v is User =>
    typeof v === 'object' &&
    v !== null &&
    hasOwnProperty(v, 'name') &&
    typeof v.name === 'string' &&
    hasOwnProperty(v, 'age') &&
    typeof v.age === 'number'

    declare const value: unknown

    if (isUser(value)) {
    console.log(`User(name = ${value.name}, age = ${value.age})`)
    } else {
    throw `Invalid user provided: ${JSON.stringify(value)}`
    }
    ```
    We created the `v is User` type guard as the return value of the `isUser` function, which tells TypeScript that if `isUser(value)` returns true, then `value` is a `User` in the `if` branch, otherwise keep the initial type, which is `unknown` here.

    You can also check the official [documentation about type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types).

    ### Type inference
    @@ -398,6 +368,41 @@ if (value.kind === 'a') {

    More examples are available in the [type guard](#type-guard) section.

    ### Type predicate

    The developer can define type guards specific to his domain by returning a _type predicate_ to a function. A type predicate uses the `paramName is Type` syntax.

    ##### Example
    ```ts
    interface User {
    name: string
    age: number
    }

    // You can ignore this function for the sake of this example
    const hasOwnProperty = <A extends {}, B extends PropertyKey>(obj: A, prop: B): obj is A & Record<B, unknown> =>
    obj.hasOwnProperty(prop)

    const isUser = (v: unknown): v is User =>
    typeof v === 'object' &&
    v !== null &&
    hasOwnProperty(v, 'name') &&
    typeof v.name === 'string' &&
    hasOwnProperty(v, 'age') &&
    typeof v.age === 'number'

    declare const value: unknown

    if (isUser(value)) {
    console.log(`User(name = ${value.name}, age = ${value.age})`)
    } else {
    throw `Invalid user provided: ${JSON.stringify(value)}`
    }
    ```
    We created the `v is User` type predicate as the return value of the `isUser` function, which tells TypeScript that if `isUser(value)` returns true, then `value` is guaranteed to be a `User` in the `if` branch, otherwise it will keep the initial type (`unknown` here).

    Some other examples of type predicates are available in the [TypeScript documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates).

    ### Union type

    Union types were introduced in [TypeScript v1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html#union-types). It's a way of expressing mulitple possible types for a given value.
  12. ruizb revised this gist Jul 6, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -242,7 +242,7 @@ Types `A`, `B`, `C` and `D` are all uniform mappings of `Config` thanks to the b
    - `C` is computed as:
    ```ts
    {
    logslevel: 'none' | 'error' | 'warning' | 'info' | 'debug' | undefined
    logslevel: 'none' | 'error' | 'warning' | 'info' | 'debug'
    }
    ```
  13. ruizb revised this gist Jul 2, 2020. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -20,6 +20,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    - [Type alias](#type-alias)
    - [Type check](#type-check)
    - [Type guard](#type-guard)
    - [Type inference](#type-inference)
    - [Type narrowing](#type-narrowing)
    @@ -284,6 +285,18 @@ type Predicate_2<A> = (value: A) => boolean
    You can go to the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases) regarding type aliases for more information.
    ### Type check
    Type checking is one of the features available with the TypeScript language. The type checker verifies the semantics of the types of your project to make sure the program is "correct" type-wise. Other features included in TypeScript are code parsing, code transformations (TS/JS => JS), language service for tools that allow e.g. [IntelliSense](#intellisense).
    If a line of code doesn't type check then a [diagnostic](#diagnostic-message) is generated and displayed as an error/warning to the user.
    ##### Example
    ```ts
    const name: string = 12
    ```
    Here, the type checker tells us there is an error for the type of `name`: `Type '12' is not assignable to type 'string'.`.

    ### Type guard

    A type guard, whether it's built into the TypeScript language or provided by the developer, allows for a type to be [narrowed](#type-narrowing) in a conditional branch.
  14. ruizb revised this gist Jul 2, 2020. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -15,6 +15,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Conditional type](#conditional-type)
    - [Diagnostic message](#diagnostic-message)
    - [Discriminated union](#discriminated-union)
    - [IntelliSense](#intellisense)
    - [Intersection type](#intersection-type)
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    @@ -111,6 +112,10 @@ Here, `Shape` is the discriminated union, where the discriminant - also known as
    You can also check the official [documentation section on discriminated unions](https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions).
    ### IntelliSense
    IntelliSense is the ability for the IDE - thanks to the language - to provide valuable hints for the developer depending on the context he's in, such as relevant and accurate autocompletions and code transformations. Usually, IDEs provide this feature via the `ctrl + space` shortcut.
    ### Intersection type
    Intersection types were introduced in [TypeScript v1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html#intersection-types) as a complement to [union types](#union-type). This allows us to type a value that is both a `A` and a `B`.
  15. ruizb revised this gist Jul 2, 2020. 1 changed file with 29 additions and 0 deletions.
    29 changes: 29 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Intersection type](#intersection-type)
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    - [Type alias](#type-alias)
    - [Type guard](#type-guard)
    - [Type inference](#type-inference)
    - [Type narrowing](#type-narrowing)
    @@ -250,6 +251,34 @@ Types `A`, `B`, `C` and `D` are all uniform mappings of `Config` thanks to the b
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    ### Type alias
    A type alias attaches a name to the definition of a type, whatever its complexity. In addition to naming function and object types like _interfaces_, type aliases can be used to name primitives, unions, tuples... Whatever type actually.
    ##### Example
    ```ts
    type Name = string
    type LazyName = () => string

    interface User_1 {
    name: string
    age: number
    }

    type User_2 = {
    name: string
    age: number
    }

    interface Predicate_1<A> {
    (value: A): boolean
    }

    type Predicate_2<A> = (value: A) => boolean
    ```
    You can go to the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases) regarding type aliases for more information.
    ### Type guard
    A type guard, whether it's built into the TypeScript language or provided by the developer, allows for a type to be [narrowed](#type-narrowing) in a conditional branch.
  16. ruizb revised this gist Jul 2, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,9 +2,9 @@

    ## Motivation

    Once upon a time, there was a developer that had an issue with TypeScript. He wanted to share his issue with the community, but he didn't know how to properly write the title that would best describe his problem. He struggled to find the appropriate words as he didn't know how to name "this behavior" or "that kind of type mechanism". After hours of reflexion, he ended up posting an issue with a [pretty awkward title](https://github.com/microsoft/TypeScript/issues/39357).
    Once upon a time, there was a developer that had an issue using the TypeScript language. He wanted to share his issue with the community to get help, but he didn't know how to properly write the title that would best describe his problem. He struggled to find the appropriate words as he didn't know how to name "this behavior" or "that kind of type mechanism".

    This story encouraged me to start writing _a glossary of TypeScript_. Hopefully it will help you if you have to look for an issue, or write an issue, or communicate with other TypeScript developers.
    This story encouraged me to start writing _a glossary of TypeScript_. Hopefully it will help you if you have to look for an issue, write an issue, or communicate with other TypeScript developers.

    Disclaimer: it was me, I was the developer that struggled. I still struggle though, but this means I still have things to learn, which is great!

  17. ruizb revised this gist Jul 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@

    Once upon a time, there was a developer that had an issue with TypeScript. He wanted to share his issue with the community, but he didn't know how to properly write the title that would best describe his problem. He struggled to find the appropriate words as he didn't know how to name "this behavior" or "that kind of type mechanism". After hours of reflexion, he ended up posting an issue with a [pretty awkward title](https://github.com/microsoft/TypeScript/issues/39357).

    This story encouraged me to start writing _a glossary of TypeScript_. Hopefully it will help you if you have to write an issue or communicate with other TypeScript developers.
    This story encouraged me to start writing _a glossary of TypeScript_. Hopefully it will help you if you have to look for an issue, or write an issue, or communicate with other TypeScript developers.

    Disclaimer: it was me, I was the developer that struggled. I still struggle though, but this means I still have things to learn, which is great!

  18. ruizb revised this gist Jul 2, 2020. 1 changed file with 152 additions and 152 deletions.
    304 changes: 152 additions & 152 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -12,84 +12,75 @@ You may not agree with some definitions or examples in this document. Please, fe

    ## Table on content

    - [Type inference](#type-inference)
    - [Literal type](#literal-type)
    - [Union type](#union-type)
    - [Conditional type](#conditional-type)
    - [Diagnostic message](#diagnostic-message)
    - [Discriminated union](#discriminated-union)
    - [Intersection type](#intersection-type)
    - [Literal type](#literal-type)
    - [Mapped type](#mapped-type)
    - [Type guard](#type-guard)
    - [Type inference](#type-inference)
    - [Type narrowing](#type-narrowing)
    - [Mapped type](#mapped-type)
    - [Conditional type](#conditional-type)
    - [Diagnostic message](#diagnostic-message)
    - [Union type](#union-type)

    ## Glossary

    ### Type inference

    Type inference is the ability for the TypeScript compiler to appropriately _guess_ the type of a value, without manually specifying the type for that value.

    ##### Example
    ```ts
    const username = 'Bob'
    const port = 8080
    const names = ['Bob', 'Henri', 'Elizabeth']
    const finiteNames = ['Bob', 'Henri', 'Elizabeth'] as const
    ```
    - Type of `username` is the [string literal type](#literal-type) `'Bob'`
    - Type of `port` is the [number literal type](#literal-type) `8080`
    - Type of `names` is `string[]`
    - Type of `finiteNames` is `readonly ['Bob', 'Henri', 'Elizabeth']`, in other words a _readonly_ tuple of 3 elements
    ### Conditional type

    ### Literal type
    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform type mapping_, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.

    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".
    TypeScript provides several conditional types for the developers, such as `Exclude`, `NonNullable`, `Parameters` or `ReturnType`.

    ##### Example
    ```ts
    type Scheme = 'http' | 'https'
    // { "strict": true }

    const prependWithScheme = (scheme: Scheme, domain: string, path: string): string =>
    `${scheme}://${domain}/${path}`
    const isDefined = <A>(value: A | null | undefined): value is NonNullable<A> =>
    value !== null && value !== undefined

    prependWithScheme('http')
    prependWithScheme('https')
    prependWithScheme('')
    const button = document.getElementById('my-button') // HTMLElement | null
    if (isDefined(button)) {
    console.log(`Button text: ${button.innerText}`)
    } else {
    console.log('Button is not defined')
    }
    ```
    Here, no TypeScript error is raised for `prependWithScheme('http')` and `prependWithScheme('https')`. Even better, the IDE knows which values are available for autocompletion. However, an error is raised for `prependWithScheme('')` as the empty string `''` is not available in the string literal type `Scheme`.
    In this example we are using the conditional type `NonNullable` in _strict mode_ as a [type guard](#type-guard) to make sure the value is defined in the "true" branch of our condition.

    ##### Example
    ```ts
    interface SuccesfulResponse {
    successfulRequest: true
    status: 200 | 201 | 202
    data: unknown
    }

    interface UnsuccesfulResponse {
    successfulRequest: false
    status: 400 | 500
    errorMessage: string
    }
    type SyncOperationName = 'getViewportSize' | 'getElementSize'
    type AsyncOperationName = 'loadUsers' | 'sendData'
    type OperationName = SyncOperationName | AsyncOperationName

    const handleResponse = (response: SuccesfulResponse | UnsuccesfulResponse): void => {
    if (response.successfulRequest) {
    console.log(`Status: ${response.status}, data: ${response.data}`)
    } else {
    console.log(`Status: ${response.status}, error message: ${response.errorMessage}`)
    }
    }
    type Operation<A extends OperationName> = A extends SyncOperationName
    ? { type: 'syncOperation', name: A }
    : { type: 'asyncOperation', name: A, timeout: number }
    ```
    Here we are mapping `A` to a completely different type `Operation<A>`, which depends on the effective type of `A`:
    - If `A` is a `SyncOperationName` then `Operation<A>` is `{ type: 'syncOperation', name: A }`.
    - Otherwise, since `A` is a `OperationName`, `OperationName` is a [union type](#union-type) and the first element of that union type has already been checked with `A extends SyncOperationName`, then `A` must be a `AsyncOperationName` in the "else" branch of this ternary expression. Therefore, `Operation<A>` becomes `{ type: 'asyncOperation', name: A, timeout: number }`.
    ### Union type
    This is a very powerful feature that allows building complex types, especially when using [type inference in conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types).
    Union types were introduced in [TypeScript v1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html#union-types). It's a way of expressing mulitple possible types for a given value.
    You can check the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types) for more information about conditional types.
    ### Diagnostic message
    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) generates a diagnostic message.
    ##### Example
    ```ts
    declare const value: string | number | boolean
    // { "strict": true }

    const value: string = undefined
    ```
    Here, `value` type can be either `string`, `number` or `boolean`.
    ```txt
    Type 'undefined' is not assignable to type 'string'. (2322)
    ```
    The `2322` number is an ID that could be used to reference the type of diagnostic message when creating an issue for example. More specifically, the `2322` ID [relates to the `Type '{0}' is not assignable to type '{1}'.` diagnostic](https://github.com/microsoft/TypeScript/blob/master/src/compiler/diagnosticMessages.json#L1285-L1288). You can also check the [wiki](https://github.com/microsoft/TypeScript/wiki/Coding-guidelines#diagnostic-message-codes) for more information about these messages.
    ### Discriminated union
    @@ -149,90 +140,45 @@ Here, `A` is `never`, because the [string literals](#literal-type) `'a'` and `'b
    For `B`, its type results in `{ name: never, age: number, adult: boolean }` because `string` and `number` have nothing in common. As one of its properties type is `never`, there's no way to create a value which type is `B`, because no value can be assigned to the `never` type.
    ### Type guard
    ### Literal type
    A type guard, whether it's built into the TypeScript language or provided by the developer, allows for a type to be [narrowed](#type-narrowing) in a conditional branch.
    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".
    ##### Example
    ```ts
    declare const value: string | number

    const getNumberOfChars = (s: string): number => s.length
    type Scheme = 'http' | 'https'

    const isGreaterThan = (n: number, bound: number): boolean => n > bound
    const prependWithScheme = (scheme: Scheme, domain: string, path: string): string =>
    `${scheme}://${domain}/${path}`

    if (typeof value === 'string') {
    console.log(`Number of chars in ${value}: ${getNumberOfChars(value)}.`)
    } else if (typeof value === 'number') {
    console.log(`Is ${value} greater than 20? ${isGreaterThan(value, 20) ? 'Yes' : 'No'}.`)
    } else {
    throw 'Impossible, perhaps the archives are incomplete'
    }
    prependWithScheme('http')
    prependWithScheme('https')
    prependWithScheme('')
    ```
    By checking the type of `value` with `typeof`, TypeScript knows that in the `if` branch, `value` must have _that_ type and not the others:
    - In the `if (typeof value === 'string') { ... }` branch, `value` type is narrowed from `string | number` to `string`.
    - In the `if (typeof value === 'number') { ... }` branch, `value` type is narrowed from `string | number` to `number`.
    - In the `else { ... }` branch, since all the possible types have been checked in the previous `if` conditions, `value` type is narrowed from `string | number` to `never` (it "can't" happen since all the possible cases have been checked already).

    The developer can also create its own type guards thanks to the `is` syntax.
    Here, no TypeScript error is raised for `prependWithScheme('http')` and `prependWithScheme('https')`. Even better, the IDE knows which values are available for autocompletion. However, an error is raised for `prependWithScheme('')` as the empty string `''` is not available in the string literal type `Scheme`.

    ##### Example
    ```ts
    interface User {
    name: string
    age: number
    interface SuccesfulResponse {
    successfulRequest: true
    status: 200 | 201 | 202
    data: unknown
    }

    // You can ignore this function for the sake of this example
    const hasOwnProperty = <A extends {}, B extends PropertyKey>(obj: A, prop: B): obj is A & Record<B, unknown> =>
    obj.hasOwnProperty(prop)

    const isUser = (v: unknown): v is User =>
    typeof v === 'object' &&
    v !== null &&
    hasOwnProperty(v, 'name') &&
    typeof v.name === 'string' &&
    hasOwnProperty(v, 'age') &&
    typeof v.age === 'number'

    declare const value: unknown

    if (isUser(value)) {
    console.log(`User(name = ${value.name}, age = ${value.age})`)
    } else {
    throw `Invalid user provided: ${JSON.stringify(value)}`
    interface UnsuccesfulResponse {
    successfulRequest: false
    status: 400 | 500
    errorMessage: string
    }
    ```
    We created the `v is User` type guard as the return value of the `isUser` function, which tells TypeScript that if `isUser(value)` returns true, then `value` is a `User` in the `if` branch, otherwise keep the initial type, which is `unknown` here.

    You can also check the official [documentation about type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types).

    ### Type narrowing

    It's the ability for the TypeScript language to restrict the type of a value to a subset of that type.

    ##### Example
    ```ts
    type A =
    | { kind: 'a', arg1: 'hey' }
    | { kind: 'b', arg1: 'Hello', arg2: 'World' }
    | { kind: 'c' }

    declare const value: A

    if (value.kind === 'a') {
    console.log(`Value of kind ${value.kind} has argument ${value.arg1}`)
    } else if (value.kind === 'b') {
    console.log(`Value of kind ${value.kind} has arguments ${value.arg1} and ${value.arg2}`)
    } else {
    console.log(`Value of kind ${value.kind} has no argument`)
    const handleResponse = (response: SuccesfulResponse | UnsuccesfulResponse): void => {
    if (response.successfulRequest) {
    console.log(`Status: ${response.status}, data: ${response.data}`)
    } else {
    console.log(`Status: ${response.status}, error message: ${response.errorMessage}`)
    }
    }
    ```
    - If `value.kind === 'a'` is true, then `value` type is `{ kind: 'a', arg1: 'hey' }`
    - Otherwise, if `value.kind === 'b'` is true, then `value` type is `{ kind: 'b', arg1: 'Hello', arg2: 'World' }`
    - Otherwise, since we've already handled the cases `{ kind: 'a', arg1: 'hey' }` and `{ kind: 'b', arg1: 'Hello', arg2: 'World' }`, only the last one of the [discriminated union `A`](#discriminated-union) is left, i.e. `{ kind: 'c' }`

    More examples are available in the [type guard](#type-guard) section.

    ### Mapped type

    @@ -302,61 +248,115 @@ Types `A`, `B`, `C` and `D` are all uniform mappings of `Config` thanks to the b
    }
    ```
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    ### Conditional type
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform type mapping_, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.
    ### Type guard
    TypeScript provides several conditional types for the developers, such as `Exclude`, `NonNullable`, `Parameters` or `ReturnType`.
    A type guard, whether it's built into the TypeScript language or provided by the developer, allows for a type to be [narrowed](#type-narrowing) in a conditional branch.
    ##### Example
    ```ts
    // { "strict": true }
    declare const value: string | number

    const isDefined = <A>(value: A | null | undefined): value is NonNullable<A> =>
    value !== null && value !== undefined
    const getNumberOfChars = (s: string): number => s.length

    const button = document.getElementById('my-button') // HTMLElement | null
    if (isDefined(button)) {
    console.log(`Button text: ${button.innerText}`)
    const isGreaterThan = (n: number, bound: number): boolean => n > bound

    if (typeof value === 'string') {
    console.log(`Number of chars in ${value}: ${getNumberOfChars(value)}.`)
    } else if (typeof value === 'number') {
    console.log(`Is ${value} greater than 20? ${isGreaterThan(value, 20) ? 'Yes' : 'No'}.`)
    } else {
    console.log('Button is not defined')
    throw 'Impossible, perhaps the archives are incomplete'
    }
    ```
    In this example we are using the conditional type `NonNullable` in _strict mode_ as a [type guard](#type-guard) to make sure the value is defined in the "true" branch of our condition.
    By checking the type of `value` with `typeof`, TypeScript knows that in the `if` branch, `value` must have _that_ type and not the others:
    - In the `if (typeof value === 'string') { ... }` branch, `value` type is narrowed from `string | number` to `string`.
    - In the `if (typeof value === 'number') { ... }` branch, `value` type is narrowed from `string | number` to `number`.
    - In the `else { ... }` branch, since all the possible types have been checked in the previous `if` conditions, `value` type is narrowed from `string | number` to `never` (it "can't" happen since all the possible cases have been checked already).

    The developer can also create its own type guards thanks to the `is` syntax.

    ##### Example
    ```ts
    type SyncOperationName = 'getViewportSize' | 'getElementSize'
    type AsyncOperationName = 'loadUsers' | 'sendData'
    type OperationName = SyncOperationName | AsyncOperationName
    interface User {
    name: string
    age: number
    }

    type Operation<A extends OperationName> = A extends SyncOperationName
    ? { type: 'syncOperation', name: A }
    : { type: 'asyncOperation', name: A, timeout: number }
    // You can ignore this function for the sake of this example
    const hasOwnProperty = <A extends {}, B extends PropertyKey>(obj: A, prop: B): obj is A & Record<B, unknown> =>
    obj.hasOwnProperty(prop)

    const isUser = (v: unknown): v is User =>
    typeof v === 'object' &&
    v !== null &&
    hasOwnProperty(v, 'name') &&
    typeof v.name === 'string' &&
    hasOwnProperty(v, 'age') &&
    typeof v.age === 'number'

    declare const value: unknown

    if (isUser(value)) {
    console.log(`User(name = ${value.name}, age = ${value.age})`)
    } else {
    throw `Invalid user provided: ${JSON.stringify(value)}`
    }
    ```
    Here we are mapping `A` to a completely different type `Operation<A>`, which depends on the effective type of `A`:
    - If `A` is a `SyncOperationName` then `Operation<A>` is `{ type: 'syncOperation', name: A }`.
    - Otherwise, since `A` is a `OperationName`, `OperationName` is a [union type](#union-type) and the first element of that union type has already been checked with `A extends SyncOperationName`, then `A` must be a `AsyncOperationName` in the "else" branch of this ternary expression. Therefore, `Operation<A>` becomes `{ type: 'asyncOperation', name: A, timeout: number }`.
    We created the `v is User` type guard as the return value of the `isUser` function, which tells TypeScript that if `isUser(value)` returns true, then `value` is a `User` in the `if` branch, otherwise keep the initial type, which is `unknown` here.

    This is a very powerful feature that allows building complex types, especially when using [type inference in conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types).
    You can also check the official [documentation about type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types).

    You can check the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types) for more information about conditional types.
    ### Type inference

    ### Diagnostic message
    Type inference is the ability for the TypeScript compiler to appropriately _guess_ the type of a value, without manually specifying the type for that value.

    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) generates a diagnostic message.
    ##### Example
    ```ts
    const username = 'Bob'
    const port = 8080
    const names = ['Bob', 'Henri', 'Elizabeth']
    const finiteNames = ['Bob', 'Henri', 'Elizabeth'] as const
    ```
    - Type of `username` is the [string literal type](#literal-type) `'Bob'`
    - Type of `port` is the [number literal type](#literal-type) `8080`
    - Type of `names` is `string[]`
    - Type of `finiteNames` is `readonly ['Bob', 'Henri', 'Elizabeth']`, in other words a _readonly_ tuple of 3 elements

    ### Type narrowing

    It's the ability for the TypeScript language to restrict the type of a value to a subset of that type.

    ##### Example
    ```ts
    // { "strict": true }
    type A =
    | { kind: 'a', arg1: 'hey' }
    | { kind: 'b', arg1: 'Hello', arg2: 'World' }
    | { kind: 'c' }

    const value: string = undefined
    ```
    declare const value: A

    ```txt
    Type 'undefined' is not assignable to type 'string'. (2322)
    if (value.kind === 'a') {
    console.log(`Value of kind ${value.kind} has argument ${value.arg1}`)
    } else if (value.kind === 'b') {
    console.log(`Value of kind ${value.kind} has arguments ${value.arg1} and ${value.arg2}`)
    } else {
    console.log(`Value of kind ${value.kind} has no argument`)
    }
    ```
    - If `value.kind === 'a'` is true, then `value` type is `{ kind: 'a', arg1: 'hey' }`
    - Otherwise, if `value.kind === 'b'` is true, then `value` type is `{ kind: 'b', arg1: 'Hello', arg2: 'World' }`
    - Otherwise, since we've already handled the cases `{ kind: 'a', arg1: 'hey' }` and `{ kind: 'b', arg1: 'Hello', arg2: 'World' }`, only the last one of the [discriminated union `A`](#discriminated-union) is left, i.e. `{ kind: 'c' }`

    More examples are available in the [type guard](#type-guard) section.

    ### Union type

    Union types were introduced in [TypeScript v1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html#union-types). It's a way of expressing mulitple possible types for a given value.

    The `2322` number is an ID that could be used to reference the type of diagnostic message when creating an issue for example. More specifically, the `2322` ID [relates to the `Type '{0}' is not assignable to type '{1}'.` diagnostic](https://github.com/microsoft/TypeScript/blob/master/src/compiler/diagnosticMessages.json#L1285-L1288). You can also check the [wiki](https://github.com/microsoft/TypeScript/wiki/Coding-guidelines#diagnostic-message-codes) for more information about these messages.
    ##### Example
    ```ts
    declare const value: string | number | boolean
    ```
    Here, `value` type can be either `string`, `number` or `boolean`.
  19. ruizb revised this gist Jul 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -43,7 +43,7 @@ const finiteNames = ['Bob', 'Henri', 'Elizabeth'] as const

    ### Literal type

    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".
    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".

    ##### Example
    ```ts
  20. ruizb revised this gist Jul 2, 2020. 1 changed file with 31 additions and 8 deletions.
    39 changes: 31 additions & 8 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    ## Table on content

    - [Type inference](#type-inference)
    - [String literal type](#string-literal-type)
    - [Literal type](#literal-type)
    - [Union type](#union-type)
    - [Discriminated union](#discriminated-union)
    - [Intersection type](#intersection-type)
    @@ -36,14 +36,14 @@ const port = 8080
    const names = ['Bob', 'Henri', 'Elizabeth']
    const finiteNames = ['Bob', 'Henri', 'Elizabeth'] as const
    ```
    - Type of `username` is the [string literal type](#string-literal-type) `'Bob'`
    - Type of `port` is `8080`
    - Type of `username` is the [string literal type](#literal-type) `'Bob'`
    - Type of `port` is the [number literal type](#literal-type) `8080`
    - Type of `names` is `string[]`
    - Type of `finiteNames` is `readonly ['Bob', 'Henri', 'Elizabeth']`, in other words a _readonly_ tuple of 3 elements

    ### String literal type
    ### Literal type

    String literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). It is meant to expect only a specific set of strings, instead of "any string".
    Literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#literal-types). They are meant to expect only a specific set of strings, numbers or boolean, instead of "**any** string, number or boolean".

    ##### Example
    ```ts
    @@ -56,7 +56,30 @@ prependWithScheme('http')
    prependWithScheme('https')
    prependWithScheme('')
    ```
    Here, no TypeScript error is raised for `prependWithScheme('http')` and `prependWithScheme('https')`. Even better, the IDE knows which values are available for autocompletion. However, an error is raised for `prependWithScheme('')` as the empty string `''` is not availalbe in the string literal type `Scheme`.
    Here, no TypeScript error is raised for `prependWithScheme('http')` and `prependWithScheme('https')`. Even better, the IDE knows which values are available for autocompletion. However, an error is raised for `prependWithScheme('')` as the empty string `''` is not available in the string literal type `Scheme`.

    ##### Example
    ```ts
    interface SuccesfulResponse {
    successfulRequest: true
    status: 200 | 201 | 202
    data: unknown
    }

    interface UnsuccesfulResponse {
    successfulRequest: false
    status: 400 | 500
    errorMessage: string
    }

    const handleResponse = (response: SuccesfulResponse | UnsuccesfulResponse): void => {
    if (response.successfulRequest) {
    console.log(`Status: ${response.status}, data: ${response.data}`)
    } else {
    console.log(`Status: ${response.status}, error message: ${response.errorMessage}`)
    }
    }
    ```

    ### Union type

    @@ -122,7 +145,7 @@ type A = 'a' & 'b'

    type B = { name: string, age: number } & { name: number, adult: boolean }
    ```
    Here, `A` is `never`, because the [string literals](#string-literal-type) `'a'` and `'b'` have nothing in common.
    Here, `A` is `never`, because the [string literals](#literal-type) `'a'` and `'b'` have nothing in common.
    For `B`, its type results in `{ name: never, age: number, adult: boolean }` because `string` and `number` have nothing in common. As one of its properties type is `never`, there's no way to create a value which type is `B`, because no value can be assigned to the `never` type.
    @@ -215,7 +238,7 @@ More examples are available in the [type guard](#type-guard) section.

    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). They can be used to make _uniform type mapping_, allowing a developer to transform a type into another type of the same "form":

    - A mapped type can use a string or subset of a string (i.e. [string literal type](#string-literal-type)) to build an object thanks to the built-in `Record` mapped type:
    - A mapped type can use a string or subset of a string (i.e. [string literal type](#literal-type)) to build an object thanks to the built-in `Record` mapped type:
    ```ts
    type A = Record<'firstname' | 'lastname' | 'surname', string>
    /**
  21. ruizb revised this gist Jul 2, 2020. 1 changed file with 19 additions and 0 deletions.
    19 changes: 19 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,7 @@ You may not agree with some definitions or examples in this document. Please, fe

    ## Table on content

    - [Type inference](#type-inference)
    - [String literal type](#string-literal-type)
    - [Union type](#union-type)
    - [Discriminated union](#discriminated-union)
    @@ -24,6 +25,22 @@ You may not agree with some definitions or examples in this document. Please, fe

    ## Glossary

    ### Type inference

    Type inference is the ability for the TypeScript compiler to appropriately _guess_ the type of a value, without manually specifying the type for that value.

    ##### Example
    ```ts
    const username = 'Bob'
    const port = 8080
    const names = ['Bob', 'Henri', 'Elizabeth']
    const finiteNames = ['Bob', 'Henri', 'Elizabeth'] as const
    ```
    - Type of `username` is the [string literal type](#string-literal-type) `'Bob'`
    - Type of `port` is `8080`
    - Type of `names` is `string[]`
    - Type of `finiteNames` is `readonly ['Bob', 'Henri', 'Elizabeth']`, in other words a _readonly_ tuple of 3 elements

    ### String literal type

    String literal types were introduced in [TypeScript v1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html#string-literal-types). It is meant to expect only a specific set of strings, instead of "any string".
    @@ -300,6 +317,8 @@ Here we are mapping `A` to a completely different type `Operation<A>`, which dep
    - If `A` is a `SyncOperationName` then `Operation<A>` is `{ type: 'syncOperation', name: A }`.
    - Otherwise, since `A` is a `OperationName`, `OperationName` is a [union type](#union-type) and the first element of that union type has already been checked with `A extends SyncOperationName`, then `A` must be a `AsyncOperationName` in the "else" branch of this ternary expression. Therefore, `Operation<A>` becomes `{ type: 'asyncOperation', name: A, timeout: number }`.
    This is a very powerful feature that allows building complex types, especially when using [type inference in conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types).
    You can check the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types) for more information about conditional types.
    ### Diagnostic message
  22. ruizb revised this gist Jul 2, 2020. 1 changed file with 37 additions and 3 deletions.
    40 changes: 37 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -196,9 +196,9 @@ More examples are available in the [type guard](#type-guard) section.

    ### Mapped type

    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). Essentially, mapped types can be used to make _uniform type mapping_, allowing a developer to transform a type into another type of the same "form":
    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). They can be used to make _uniform type mapping_, allowing a developer to transform a type into another type of the same "form":

    - A mapped type can use a string or subset of a string (i.e. [string literal type](#string-literal-type) to build an object thanks to the built-in `Record` mapped type:
    - A mapped type can use a string or subset of a string (i.e. [string literal type](#string-literal-type)) to build an object thanks to the built-in `Record` mapped type:
    ```ts
    type A = Record<'firstname' | 'lastname' | 'surname', string>
    /**
    @@ -266,7 +266,41 @@ There is a [section in the official documentation](https://www.typescriptlang.or
    ### Conditional type
    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform mappings_ into other types, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.
    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform type mapping_, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.
    TypeScript provides several conditional types for the developers, such as `Exclude`, `NonNullable`, `Parameters` or `ReturnType`.
    ##### Example
    ```ts
    // { "strict": true }

    const isDefined = <A>(value: A | null | undefined): value is NonNullable<A> =>
    value !== null && value !== undefined

    const button = document.getElementById('my-button') // HTMLElement | null
    if (isDefined(button)) {
    console.log(`Button text: ${button.innerText}`)
    } else {
    console.log('Button is not defined')
    }
    ```
    In this example we are using the conditional type `NonNullable` in _strict mode_ as a [type guard](#type-guard) to make sure the value is defined in the "true" branch of our condition.

    ##### Example
    ```ts
    type SyncOperationName = 'getViewportSize' | 'getElementSize'
    type AsyncOperationName = 'loadUsers' | 'sendData'
    type OperationName = SyncOperationName | AsyncOperationName

    type Operation<A extends OperationName> = A extends SyncOperationName
    ? { type: 'syncOperation', name: A }
    : { type: 'asyncOperation', name: A, timeout: number }
    ```
    Here we are mapping `A` to a completely different type `Operation<A>`, which depends on the effective type of `A`:
    - If `A` is a `SyncOperationName` then `Operation<A>` is `{ type: 'syncOperation', name: A }`.
    - Otherwise, since `A` is a `OperationName`, `OperationName` is a [union type](#union-type) and the first element of that union type has already been checked with `A extends SyncOperationName`, then `A` must be a `AsyncOperationName` in the "else" branch of this ternary expression. Therefore, `Operation<A>` becomes `{ type: 'asyncOperation', name: A, timeout: number }`.
    You can check the [official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types) for more information about conditional types.
    ### Diagnostic message
  23. ruizb revised this gist Jul 2, 2020. 1 changed file with 34 additions and 3 deletions.
    37 changes: 34 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -19,6 +19,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Type guard](#type-guard)
    - [Type narrowing](#type-narrowing)
    - [Mapped type](#mapped-type)
    - [Conditional type](#conditional-type)
    - [Diagnostic message](#diagnostic-message)

    ## Glossary
    @@ -195,7 +196,23 @@ More examples are available in the [type guard](#type-guard) section.

    ### Mapped type

    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). They have been improved with further releases, allowing the creation of pretty complex types. Essentially, mapped types can be used as _functions for the types_, allowing a developer to transform types into other types. TypeScript provides several mapped types such as `Required`, `Partial`, `Exclude`, `Pick` and `Omit` for example.
    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). Essentially, mapped types can be used to make _uniform type mapping_, allowing a developer to transform a type into another type of the same "form":

    - A mapped type can use a string or subset of a string (i.e. [string literal type](#string-literal-type) to build an object thanks to the built-in `Record` mapped type:
    ```ts
    type A = Record<'firstname' | 'lastname' | 'surname', string>
    /**
    * {
    * firstname: string,
    * lastname: string,
    * surname: string
    * }
    */
    ```
    - A mapped type can be a subset of the original type, e.g. using `Pick` or `Omit` (cf. example below).
    - A mapped type can change the _optionality_ of all the properties of the original type using `Required`, `Nullable` or `Partial`.
    - A mapped type can change the _visibility_ of all the properties of the original type using `Readonly`.
    ##### Example
    ```ts
    @@ -208,9 +225,10 @@ interface Config {
    type A = Partial<Config>
    type B = Omit<Config, 'address' | 'logsLevel'>
    type C = Pick<Config, 'logsLevel'>
    type D = Readonly<Config>
    ```
    Types `A`, `B` and `C` are all transformations of `Config` thanks to the mapped types `Partial`, `Omit` and `Pick`:
    Types `A`, `B`, `C` and `D` are all uniform mappings of `Config` thanks to the built-in mapped types `Partial`, `Omit`, `Pick` and `Readonly`:
    - `A` is computed as:
    ```ts
    @@ -235,7 +253,20 @@ Types `A`, `B` and `C` are all transformations of `Config` thanks to the mapped
    }
    ```
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    - `D` is computed ad:
    ```ts
    {
    readonly address: string,
    readonly port: number,
    readonly logslevel: 'none' | 'error' | 'warning' | 'info' | 'debug'
    }
    ```
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    ### Conditional type
    Conditional types were introduced in [TypeScript v2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types). They can be used to make _non-uniform mappings_ into other types, meaning they can be considered as _functions for types_, like [mapped types](#mapped-type) but more powerful.
    ### Diagnostic message
  24. ruizb revised this gist Jul 2, 2020. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -235,6 +235,8 @@ Types `A`, `B` and `C` are all transformations of `Config` thanks to the mapped
    }
    ```
    There is a [section in the official documentation](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types) about mapped types.
    ### Diagnostic message
    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) generates a diagnostic message.
  25. ruizb revised this gist Jul 2, 2020. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -221,7 +221,13 @@ Types `A`, `B` and `C` are all transformations of `Config` thanks to the mapped
    }
    ```
    - `B` is computed as `{ port: number }`.
    - `B` is computed as:
    ```ts
    {
    port: number
    }
    ```
    - `C` is computed as:
    ```ts
    {
  26. ruizb revised this gist Jul 2, 2020. 1 changed file with 37 additions and 0 deletions.
    37 changes: 37 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,7 @@ You may not agree with some definitions or examples in this document. Please, fe
    - [Intersection type](#intersection-type)
    - [Type guard](#type-guard)
    - [Type narrowing](#type-narrowing)
    - [Mapped type](#mapped-type)
    - [Diagnostic message](#diagnostic-message)

    ## Glossary
    @@ -192,6 +193,42 @@ if (value.kind === 'a') {

    More examples are available in the [type guard](#type-guard) section.

    ### Mapped type

    Mapped types were introduced in [TypeScript v2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#mapped-types). They have been improved with further releases, allowing the creation of pretty complex types. Essentially, mapped types can be used as _functions for the types_, allowing a developer to transform types into other types. TypeScript provides several mapped types such as `Required`, `Partial`, `Exclude`, `Pick` and `Omit` for example.

    ##### Example
    ```ts
    interface Config {
    address: string
    port: number
    logsLevel: 'none' | 'error' | 'warning' | 'info' | 'debug'
    }

    type A = Partial<Config>
    type B = Omit<Config, 'address' | 'logsLevel'>
    type C = Pick<Config, 'logsLevel'>
    ```
    Types `A`, `B` and `C` are all transformations of `Config` thanks to the mapped types `Partial`, `Omit` and `Pick`:
    - `A` is computed as:
    ```ts
    {
    address?: string | undefined,
    port?: number | undefined,
    logslevel?: 'none' | 'error' | 'warning' | 'info' | 'debug' | undefined
    }
    ```
    - `B` is computed as `{ port: number }`.
    - `C` is computed as:
    ```ts
    {
    logslevel: 'none' | 'error' | 'warning' | 'info' | 'debug' | undefined
    }
    ```
    ### Diagnostic message
    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) generates a diagnostic message.
  27. ruizb revised this gist Jul 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ This story encouraged me to start writing _a glossary of TypeScript_. Hopefully

    Disclaimer: it was me, I was the developer that struggled. I still struggle though, but this means I still have things to learn, which is great!

    You may not agree with some definitions or examples in this document. Please, feel free to leave a comment and let me know, only together can we improve this glossary! Also, if the stars are aligned and this _gist_ gets more and more used, I might move it into its own repository so we can all contribute via issues and pull-requests! :rocket:
    You may not agree with some definitions or examples in this document. Please, feel free to leave a comment and let me know, only together can we improve this glossary! Also, if the stars are aligned and this _gist_ gets more and more attention, I might move it into its own repository so we can all contribute via issues and pull-requests! :rocket:

    ## Table on content

  28. ruizb revised this gist Jul 2, 2020. 1 changed file with 8 additions and 3 deletions.
    11 changes: 8 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -141,11 +141,16 @@ interface User {
    age: number
    }

    // You can ignore this function for the sake of this example
    const hasOwnProperty = <A extends {}, B extends PropertyKey>(obj: A, prop: B): obj is A & Record<B, unknown> =>
    obj.hasOwnProperty(prop)

    const isUser = (v: unknown): v is User =>
    typeof v === 'object' &&
    v.hasOwnProperty('name') &&
    typeof v.name === 'string'
    v.hasOwnProperty('age') &&
    v !== null &&
    hasOwnProperty(v, 'name') &&
    typeof v.name === 'string' &&
    hasOwnProperty(v, 'age') &&
    typeof v.age === 'number'

    declare const value: unknown
  29. ruizb revised this gist Jul 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -189,7 +189,7 @@ More examples are available in the [type guard](#type-guard) section.

    ### Diagnostic message

    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) emits a diagnostic message.
    When TypeScript detects an error/warning in your program, its _checker_ (an internal component of the language) generates a diagnostic message.

    ##### Example
    ```ts
  30. ruizb revised this gist Jul 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -202,4 +202,4 @@ const value: string = undefined
    Type 'undefined' is not assignable to type 'string'. (2322)
    ```

    The `2322` number is an ID that could be used to reference the type of diagnostic message when creating an issue for example. More specifically, the `2322` ID [relates to the `Type '{0}' is not assignable to type '{1}'.` diagnostic](https://github.com/microsoft/TypeScript/blob/master/src/compiler/diagnosticMessages.json#L1285-L1288).
    The `2322` number is an ID that could be used to reference the type of diagnostic message when creating an issue for example. More specifically, the `2322` ID [relates to the `Type '{0}' is not assignable to type '{1}'.` diagnostic](https://github.com/microsoft/TypeScript/blob/master/src/compiler/diagnosticMessages.json#L1285-L1288). You can also check the [wiki](https://github.com/microsoft/TypeScript/wiki/Coding-guidelines#diagnostic-message-codes) for more information about these messages.