You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用TypeScript定义可选但不可为undefined的属性?

如何定义可选但存在时不能为undefined的属性?

概述

我希望禁止任何显式的undefined值,但仍允许隐式的undefined值。

背景

在JavaScript中,访问不存在的键会返回undefined,而访问存在的键也可能返回undefined。例如:

  • [1, 2, undefined, 4][2] -> undefined(显式)
  • [1, 2, 3, 4][99] -> undefined(隐式)
  • {a: 1, b: undefined}.b -> undefined(显式)
  • {a: 1, b: 2}.foo -> undefined(隐式)

其中示例1和3是访问显式为undefined的值,示例2和4是访问隐式为undefined的值。

问题

我想要定义一个可能存在也可能不存在(可选)的键,但如果它存在,则不能为undefined。这是否可行?

更多细节

我需要定义这样的类型:

// - mustExistAndCouldBeUndefined 必须存在于该类型中,但可以是undefined。
// - couldExistAndCouldBeUndefined 可能存在于该类型中。如果存在,可以是undefined;如果不存在,则为undefined。
// - couldExistButCannotBeUndefinedIfItDoes 可能存在于该类型中。如果存在,不能是undefined;如果不存在,则为undefined。
type Example = {
    mustExistAndCouldBeUndefined: number | undefined;
    couldExistAndCouldBeUndefined?: number;
    ??? couldExistButCannotBeUndefinedIfItDoes ???
};

// 期望合法:couldExistButCannotBeUndefinedIfItDoes不存在(隐式undefined)
const a: Example = {
    mustExistAndCouldBeUndefined: undefined,
};

// 期望非法:couldExistButCannotBeUndefinedIfItDoes存在但为undefined(显式undefined)
const b: Example = {
    mustExistAndCouldBeUndefined: undefined,
    couldExistButCannotBeUndefinedIfItDoes: undefined,
};

能否创建出如上代码中couldExistButCannotBeUndefinedIfItDoes这样的属性定义?


解决方案

可以通过联合类型实现这个需求,把类型拆分为「包含该属性且值为非undefined类型」和「不包含该属性」的两种情况的联合:

type Example = 
  | {
      mustExistAndCouldBeUndefined: number | undefined;
      couldExistAndCouldBeUndefined?: number;
      couldExistButCannotBeUndefinedIfItDoes: number;
    }
  | {
      mustExistAndCouldBeUndefined: number | undefined;
      couldExistAndCouldBeUndefined?: number;
      couldExistButCannotBeUndefinedIfItDoes?: never; // 用never禁止显式赋值undefined
    };

// 合法
const a: Example = {
    mustExistAndCouldBeUndefined: undefined,
};

// 非法(符合预期)
const b: Example = {
    mustExistAndCouldBeUndefined: undefined,
    couldExistButCannotBeUndefinedIfItDoes: undefined,
};

// 合法:存在该属性且值为number
const c: Example = {
    mustExistAndCouldBeUndefined: undefined,
    couldExistButCannotBeUndefinedIfItDoes: 123,
};

如果不想重复编写公共属性,可以用工具类型简化:

// 提取公共属性
type BaseExample = {
    mustExistAndCouldBeUndefined: number | undefined;
    couldExistAndCouldBeUndefined?: number;
};

// 包含目标属性的情况
type ExampleWithRequiredProp = BaseExample & {
    couldExistButCannotBeUndefinedIfItDoes: number;
};

// 不包含目标属性的情况(禁止显式赋值undefined)
type ExampleWithoutProp = BaseExample & {
    couldExistButCannotBeUndefinedIfItDoes?: never;
};

// 最终联合类型
type Example = ExampleWithRequiredProp | ExampleWithoutProp;

原理说明

  • 当类型为ExampleWithoutProp时,couldExistButCannotBeUndefinedIfItDoes被定义为?: never:
    • 允许不写这个属性,符合「可选」的要求
    • 如果强制写这个属性,只能赋值never类型的值,而undefined不属于never,因此会触发类型错误,从而禁止显式赋值undefined
  • 联合类型覆盖了「存在属性且值为number」和「不存在属性」两种合法场景,同时排除了「存在属性但值为undefined」的非法场景。

内容的提问来源于stack exchange,提问作者nullromo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:53:26