Typescript:从联合类型中排除未定义

mic*_*elT 6 typescript

Options 我创建了一个自定义类型(嵌套对象)。我想使用该类型DefaultProperties创建一个包含默认属性的对象。

type Options = {
    id: number,
    text: string | undefined,
    properties: {
        title: string,
        subtitle: string | undefined,
    }
}

type DefaultProperties = Pick<Options, "properties">;
Run Code Online (Sandbox Code Playgroud)

当然默认属性不能是undefined。所以我想undefined从我的联合类型中排除。为此,应该有一个内置函数,如NonNullable<T>或Exclude<T,UnionType>。

我尝试了三种不同的删除方法,undefined但没有解决方案适合我的类型。

type Options = {
    id: number,
    text: string | undefined,
    properties: {
        title: string,
        subtitle: string | undefined,
    }
}

type DefaultProperties = Pick<Options, "properties">;


// Try #1: does not work
type Type1 = NonNullable<DefaultProperties>;

// Try #2: does not work
type NotOptional<Type> = {
    [Property in keyof Type]-?: Type[Property];
};
type Type2 = NotOptional<DefaultProperties>;

// Try #3: does not work
type Type3 = Exclude<Options, undefined>;
Run Code Online (Sandbox Code Playgroud)

示例: TypeScript Playground

如何undefined从我的所有类型联合类型中删除所有 s?

编辑: 所有undefineds 都应该从我的类型中删除。例如:

  • Options['text'] : string(不再undefined)
  • Options['properties']['subtitle'] : string(不再undefined)

后来我想为此使用类型(例如):

const options : Options = { ... };
const defaults: DefaultProperties= { ... }; // With no undefined

const node : HTMLElement = .... ;
node.innerHTML = options.properties.subtitle !== undefined ? options.properties.subtitle : defaults.properties.subtitle;
Run Code Online (Sandbox Code Playgroud)

当defaults.properties.subtitle有类型时string | undefined,编译器会抛出错误,因为innerHTML只允许strings。为此我想排除undefined.

T.J*_*der 2

您与NotOptional实用程序类型和非常接近Exclude,问题是您定义DefaultProperties为具有属性的对象properties,但您试图undefined从 中删除DefaultProperties,而不是从其properties属性中删除。

在评论中,您说过您希望与上的DefaultProperties形状相同。这意味着它的基本形状(在我们尝试删除 之前)是。所以:propertiesOptionsundefinedOptions["properties"]

type NotOptional<Type> = {
    [Property in keyof Type]: Exclude<Type[Property], undefined>;
};

type DefaultProperties = NotOptional<Options["properties"]>;
Run Code Online (Sandbox Code Playgroud)

测试:

const defaults1: DefaultProperties = {
    title: "foo",
    subtitle: undefined,    // <== Error as desired
};

const defaults2: DefaultProperties = {
    title: "foo",
    subtitle: "something",  // <== No error
};
Run Code Online (Sandbox Code Playgroud)

游乐场链接

您还可以考虑删除可选性(结合您尝试过的两项):

type NotOptional<Type> = {
    [Property in keyof Type]-?: Exclude<Type[Property], undefined>;
};

type DefaultProperties = NotOptional<Options["properties"]>;
Run Code Online (Sandbox Code Playgroud)

测试:

const defaults1: DefaultProperties = {
    title: "foo",
    subtitle: undefined,    // <== Error as desired (wrong type for `subtitle`)
};

const defaults2: DefaultProperties = {  // <== Error as desired (missing `somethingElse`)
    title: "foo",
    subtitle: "something",
};

const defaults3: DefaultProperties = {  // <== No error
    title: "foo",
    subtitle: "something",  // <== No error
    somethingElse: "x",
};
Run Code Online (Sandbox Code Playgroud)

游乐场链接