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

如何在TypeScript中添加数组类型注解同时提取对象属性联合类型?

如何为数组添加类型注解同时保留属性的联合类型推导?

我尝试从对象数组的属性中推导联合类型:

const fontLib = [
  {
    name: 'foo',
    subsets: ['latin'],
  },
  {
    name: 'bar',
    subsets: ['latin'],
  },
] as const;

type FontName = (typeof fontLib)[number]['name'];

此时FontName类型会如预期般为'foo'|'bar'。

但当我为fontLib添加类型注解后,推断出的类型会被注解类型覆盖:

const fontLib: FontLib[] = [
    {
        name: 'foo',
        subsets: ['latin'],
    },
    {
        name: 'bar',
        subsets: ['latin'],
    },
] as const;

interface FontLib<T extends string = string> {
    name: T
    subsets: string[];
}

type FontName = (typeof fontLib)[number]['name']; // 此时FontName类型为string

请问如何添加类型注解且不影响联合类型的推导?


解决方案

1. 使用泛型函数约束类型并保留字面量

通过泛型函数让TypeScript自动推导数组元素的具体字面量类型,同时约束元素符合FontLib接口:

interface FontLib<T extends string = string> {
    name: T;
    subsets: string[];
}

const createFontLib = <T extends string>(fonts: readonly FontLib<T>[]) => fonts;

const fontLib = createFontLib([
    {
        name: 'foo',
        subsets: ['latin'],
    },
    {
        name: 'bar',
        subsets: ['latin'],
    },
] as const);

type FontName = (typeof fontLib)[number]['name']; // 'foo' | 'bar'

2. 使用satisfies关键字(TypeScript 4.9+)

satisfies关键字可以确保值符合指定类型约束,但不会覆盖原本的字面量类型推导,是最简洁的方案:

interface FontLib<T extends string = string> {
    name: T;
    subsets: string[];
}

const fontLib = [
    {
        name: 'foo',
        subsets: ['latin'],
    },
    {
        name: 'bar',
        subsets: ['latin'],
    },
] as const satisfies readonly FontLib[];

type FontName = (typeof fontLib)[number]['name']; // 'foo' | 'bar'

3. 显式指定泛型参数(手动指定联合类型)

如果不想用函数或satisfies,可以显式给FontLib传入预先定义的联合类型,但这种方式需要手动维护联合类型,灵活性较低:

type FontNames = 'foo' | 'bar';

interface FontLib<T extends string = string> {
    name: T;
    subsets: string[];
}

const fontLib: FontLib<FontNames>[] = [
    {
        name: 'foo',
        subsets: ['latin'],
    },
    {
        name: 'bar',
        subsets: ['latin'],
    },
] as const;

type FontName = (typeof fontLib)[number]['name']; // 'foo' | 'bar'

原因说明

直接给数组添加FontLib[]注解时,TypeScript会将数组元素的类型宽化为FontLib<string>(因为FontLib的默认泛型参数是string),导致name属性的字面量类型被覆盖为string。而泛型函数或satisfies可以在约束类型的同时,保留数组元素的具体字面量类型信息,从而让联合类型推导正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:18:22