Как создать целевой объект из общих частей в TypeScript? - PullRequest
0 голосов
/ 05 февраля 2019

Я использую typescript@2.3.4.

У меня есть целевой объект:

interface MyTarget {
    a: string;
    b: string;
    c: string;
    d: string;
}

Я хочу создать несколько преобразований частичных объектов с использованием шаблонов.

Один такой конвертер может выглядеть следующим образом:

const convert = <T extends object>(t: T): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...t,
    };
};

Тем не менее это приводит к:

error TS2698: Spread types may only be created from object types.

, хотя я и охраняю общий T как object.

Затем я помню, что существует тип Partial, поэтому я попробовал это:

const convert = (partial: Partial<MyTarget>): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...partial,
    };
};

И все же Partial делает все свойства необязательными.Я не хочу этого, и теперь будет выдано:

src/Partial.ts(14,5): error TS2322: Type '{ a?: string; b?: string; c: string; d: string; }' is not assignable to type 'MyTarget'.
  Property 'a' is optional in type '{ a?: string; b?: string; c: string; d: string; }' but required in type 'MyTarget'.

Я хочу создать экземпляр MyTarget с каждым полем, установленным как требование.Я хочу сохранить безопасность типов, вот почему я не хочу этого, даже если это работает:

const convert = (partial: Partial<MyTarget>): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...partial,
    } as MyTarget; // loses type checks, really don't want to
};

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Я пошел с решением Qwertiy :

interface XYZ {
  x: number;
  y: number;
  z: number;
}

declare var { z, ...xy }: XYZ;

type XY = typeof xy; // { x: number; y: number;}

, которое отлично работает для tsc@2.3.

0 голосов
/ 05 февраля 2019

Я думаю, что вы используете более старую версию TS (в более новой версии распространенные выражения набираются правильно).

Независимо от этого, истинная проблема заключается в том, что литерал объекта может быть не полным MyTarget.Ваш код разрешил бы этот вызов

convert({a : "" })// return value is not really MyTarget since it will not contain b

То, что вы действительно хотите, это параметр MyTarget за исключением c и d:

interface MyTarget {
    a: string;
    b: string;
    c: string;
    d: string;
}
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
const convert = (t: Omit<MyTarget, 'c' | 'd'>) : MyTarget => {
    return {
        c: "c",
        d: "d",
        ...t,
    };
};
...