【问题标题】:Exclude type by member type按成员类型排除类型
【发布时间】:2018-09-24 08:54:40
【问题描述】:

我有一个函数可以处理没有数据到达的情况,否则它会调用回调来处理实际数据。

我使用 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) =&gt; void 这样写回调也没有用。

有没有办法从对象成员为空的类型中删除?

【问题讨论】:

    标签: typescript typescript2.8


    【解决方案1】:

    Result 的类型不是联合,它的类型是有一个联合成员。您需要从 data 属性中排除 null

    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
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-25
      • 1970-01-01
      • 2022-12-11
      • 2021-07-25
      相关资源
      最近更新 更多