Исключить тип по типу члена - PullRequest
       15

Исключить тип по типу члена

0 голосов
/ 24 сентября 2018

У меня есть функция, которая обрабатывает ситуации, когда данные не поступают, в противном случае она вызывает обратный вызов для обработки фактических данных.

Я использую Typescript 2.8.3.

Я пробовал этоКстати, но это не работает:

interface Result { data: string | null; }

function doStuff(
    input: Result,
    cb: (str: Exclude<Result, {data: null}>) => void
): void {
    if (input.data) {
        cb({data: input.data});
    }
}

doStuff({data: "x"}, (result) => {
    alert(result.data.length); // TS2532: Object is possibly 'null'
});

Я должен сохранить Result интерфейс , потому что это сгенерированный код какой-то библиотеки GQL.Это решение работает, но не возможно для меня:

interface VoidResult { data: null; }
interface NonVoidResult { data: string; }
type Result = VoidResult | NonVoidResult;
function doStuff(
    data: Result,
    cb: (str: NonVoidResult) => void
): void { ... }

Фактический объект результата - это не строка , а сложный тип объекта, который может даже измениться в будущем.Поэтому запись обратного вызова, например cb: (str: string) => void, также бесполезна.

Есть ли способ удалить из типа, где элемент объекта имеет значение null?

1 Ответ

0 голосов
/ 24 сентября 2018

Тип Result не является объединением, это тип, в котором есть член, который является объединением.Вам необходимо исключить null из свойства data:

interface Result { data: string | null; }

function doStuff(
    input: Result,
    cb: (str: { data: Exclude<Result['data'], null> }) => void
): void {
    if (input.data) {
        cb({data: input.data});
    }
}

doStuff({data: "x"}, (result) => {
    alert(result.data.length); // ok
});

Вы даже можете создать тип, исключающий null из члена определенного типа.Это может быть полезно, если в вашем интерфейсе больше участников:

interface Result { data: string | null; }
type RemoveNullFrom<T, TKey extends keyof T> = Pick<T, Exclude<keyof T, TKey>> & {
    [P in TKey] : Exclude<T[P], null>    
}
function doStuff(
    input: Result,
    cb: (str: RemoveNullFrom<Result, 'data'>) => void
): void {
    if (input.data) {
        cb({data: input.data});
    }
}

doStuff({data: "x"}, (result) => {
    alert(result.data.length); // ok
});
...