我会保持简短和甜蜜的. 为什么会这样?

type ReadonlyStringArray = readonly string[]

type TEnumGeneric<EnumIsh extends ReadonlyStringArray> = {
    type: "enum",
    values: EnumIsh
}

type TEnumImplied = {
    type: "enum",
    values: ReadonlyStringArray
}
type EVal<T extends TEnumImplied> = {
    value: T["values"][number]
}

考虑到这一点

const somearr = ["foo", "baz", "bar"] as const
const x: TEnumGeneric<typeof somearr> = {
    type: "enum",
    values: somearr
}
const z: EVal<typeof x> = {
    value: "bar"
}

但也允许这样做吗?

const y: TEnumImplied = {
    type: "enum",
    values: ["foo", "bar", "baz"] as const
} as const
const z: EVal<typeof y> = {
    value: "" //???
}

我假设它只允许y.Values中的一个值,因为TEnumImpled的值是只读的...?

推荐答案

如果您使用的是像TEnumImplied这样的非union类型,那么这就是编译器所知道的全部.您可以为其赋值const-asserted,但这不会影响变量的类型.(也许您预期的是某种assignment narrowing,但这只发生在联合类型的变量上.)

就这样给予了

const y: TEnumImplied = {
  type: "enum",
  values: ["foo", "bar", "baz"] as const
} as const

y的类型只有TEnumImplied,与"foo""bar""baz"无关:

y
//^? const y: TEnumImplied

因此,EVal<typeof y>只是{ value: string; },因为TEnumImplied["values"][number]string:

type E = EVal<typeof y>
//   ^? type E = { value: string; }

如果你不喜欢这种行为,你就不应该注释y‘S类型.


大概你只想把那个y‘S的类型赋给TEnumImplied,而不是实际把它赋widening.这看起来像是一份the satisfies operator人的工作.你可以写const vbl = expr satisifies Type,而不是const vbl: Type = expr;.如果expr不是Type类型,两个版本都会给出错误,但注释将vbl扩展到Type,而satisfies会将vbl的类型推断为expr的类型(Type只是contextual type,以帮助进行推断).

因此,如果我们将其更改为:

const y = {
  type: "enum",
  values: ["foo", "bar", "baz"] as const
} as const satisfies TEnumImplied;

现在您将看到y的预期类型:

y
//^? const y: { 
//     readonly type: "enum"; 
//     readonly values: readonly ["foo", "bar", "baz"]; 
//   }

因此,EVal<typeof y>;的预期结果:

type E = EVal<typeof y>
//   ^? type E =  { value: "foo" | "bar" | "baz"; }

Playground link to code

Javascript相关问答推荐

为什么这个自定义组件会被放置在TR之外?

鼠标移动时更新画布

如何访问react路由v6加载器函数中的查询参数/搜索参数

具有相同参数的JS类

如何才能拥有在jQuery终端中执行命令的链接?

传递一个大对象以在Express布局中呈现

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

将本机导航路由react 到导航栏中未列出的屏幕?

如何在模块层面提供服务?

setcallback是什么时候放到macrotask队列上的?

获取Uint8ClampedArray中像素数组的宽度/高度

用于编辑CSS样式的Java脚本

如何在coCos2d-x中更正此错误

第三方包不需要NODE_MODULES文件夹就可以工作吗?

使用父标签中的Find函数查找元素

删除元素属性或样式属性的首选方法

图表4-堆叠线和条形图之间的填充区域

如何向内部有文本输入字段的HTML表添加行?

KeyboardEvent:检测到键具有打印的表示形式

在对象的嵌套数组中添加两个属性