Comment

Comment by arxanas

Explanation:

A record is a set of key-value pairs with the value having a given type (also called a struct, object, etc. depending on the context). In TypeScript, this is an example of a record:

    const foo = { bar: 1, baz: "qux" };
Destructuring is an ergonomic feature where you can take the fields of a record and assign them to local variables. For example:

    // Equivalent to
    // const bar = foo.bar;
    // const baz = foo.baz;
    const { bar, baz } = foo;
Besides ergonomics, destructuring can offer features like exhaustiveness-checking, to make sure that you used all of the fields of a record.

A union type is a type which denotes that the value is one of two different types, indicated like this:

    type Foo = number | string;
Sometimes, you have two different cases with the same type, and you want to distinguish between them. For example:

    // Not helpful -- we can't tell from the value
    // whether it's supposed to be a username or an email.
    type UsernameOrEmail = string | string;
To handle this case, you can use a discriminated union instead. These unions have a special value which unambiguously indicates which case is present:

    type UsernameOrEmail = { type: "username", value: string }
                         | { type: "email", value: string };
Sometimes, you have a discriminated union with different fields:

    type ApiRequest = { type: "message", subject: string, contents: string }
                    | { type: "view-posts", user_id: number };
Currently, TypeScript uses control-flow analysis to ensure that you're using the right kinds of fields depending on the discriminator value:

    const request: ApiRequest = getRequest();
    if (request.type === "message") {
        // Okay:
        console.log("Subject is", request.subject);
        // Rejected by compiler:
        console.log("User ID is", request.user_id);
    }
However, you can't combine this feature with destructuring:

    type Action = { kind: "A", payload: number }
                | { kind: "B", payload: string };
    
    const { kind, payload } = getAction();
    if (kind === "B") {
        // Not currently allowed:
        payload.toUpperCase();
    }
With this pull request, you can do the above. This can be convenient with patterns like reducers (see https://github.com/microsoft/TypeScript/issues/46143 for an example).
parent arxanas 5 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton