“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

Most TypeScript developers use TypeScript at a rudimentary level.

Don’t believe it? Try the TypeScript Weekly Challenge!

The second challenge will be released at 17:00 PM, 2021-07-08 (Friday)

background

There are many tool types used in TypeScript, including the common Pick

, which can be used to extract specified fields from a type, such as:

interface Type1 {
    a: string.b: boolean.c: number
}

// { a: string, b: boolean }
type Type2 = Pick<Type1, 'a' | 'b'>;
Copy the code

The problem

But if you Pick a Union Type, there may be some problems, such as the following PickData:

type Data = {
    type: 'a'.value: {
        a: string
    },
    a1: string.a2: string.// ...
} | {
    type: 'b'.value: {
        b: string
    },
    b1: string.b2: string.// ...
} | {
    type: 'c'.value: {
        c: string
    },
    c1: string.c2: string.// ...
}; // There may be more

type PickData = Pick<Data, 'type' | 'value'>;
Copy the code

As you can see, Data is a Union Type, and the value field is formatted differently depending on the value of its Type field. PickData extracts the Type and value fields, and obviously we want these two fields to retain their matching relationship in Data.

PickData is expected to be equal to:

type PickData = {
    type: 'a'.value: {
        a: string| {}}type: 'b'.value: {
        b: string
    }
    // ...
} | {
    type: 'c'.value: {
        c: string}};Copy the code

But in fact, with TypeScript conversion processing, PickData becomes :(not expected)

type PickData = {
    type: "a" | "b" | "c";
    value: {
        a: string;
    } | {
        b: string;
    } | {
        c: string;
    };
}
Copy the code

That is, the PickData parsed by TypeScript loses the field matching relationship in the Union Type.

Accordingly, this code will report an error :(not expected)

function test(data: PickData) {
    if (data.type === 'a') {
        // ERROR: Property 'a' does not exist on type '{a: string; } | { b: string; } | { c: string; } '.
        console.log(data.value.a); }}Copy the code

The subject requirements

Redefine the PickData in the problem so that it retains the mutex matching relationship in the original Data even after picking the Type and value fields.

Try to do this with minimal code volume and type redundancy.

You are welcome to leave your answers and thoughts in the comments section below. The correct answer will be posted at 17:00 PM, 2021-07-08 (Friday).

(End of text)

Review past challenges

  • Issue 1: Constraint type relationships between multiple function parameters

If you’re interested in full-stack development with TypeScript, consider TSRPC, the only open source TypeScript RPC framework in the world that supports runtime automatic detection and binary serialization of TypeScript complex types.

GitHub:github.com/k8w/tsrpc Chinese document: TSRPC. Cn video tutorial: www.bilibili.com/video/BV1hM…