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

如何在TypeScript函数中让第二个参数类型依赖第一个参数?

实现TypeScript函数参数类型的依赖约束

要让第二个参数的类型严格依赖第一个参数的具体实例,核心是让TypeScript保留用户实例中sites数组的具体字面量类型,而非被拓宽为宽泛的Site[]类型,再通过泛型提取该类型作为第二个参数的约束。以下是具体实现方案:

问题根源

原代码中ADMIN被注解为User类型,而User的sites字段定义为Site[],这会让TypeScript忽略数组的具体元素值,只保留Site联合类型,导致无法校验具体实例的sites范围。

解决方案

方式一:泛型+satisfies关键字(推荐,TypeScript 4.9+)

通过泛型User类型保留sites的具体元素类型,同时用satisfies确保常量符合User约束但不丢失类型信息:

type Site = 'ABC' | 'XYZ';

// 泛型User类型,捕获sites的具体元素类型
type User<T extends Site = Site> = {
    email: string;
    sites: readonly T[];
};

// 定义用户常量,用satisfies确保符合User类型,同时保留具体类型
const ADMIN = {
    email: 'admin@gmail.com',
    sites: ['ABC'] as const,
} satisfies User;

const MODERATOR = {
    email: 'mod@gmail.com',
    sites: ['ABC', 'XYZ'] as const,
} satisfies User;

// 泛型log函数,第二个参数类型依赖第一个参数的sites元素类型
function log<U extends User>(user: U, site: U['sites'][number]): void {
    console.log(`${user.email}/${site}`);
}

export function test(): void {
    log(ADMIN, 'ABC'); // ✅ 编译通过
    log(ADMIN, 'XYZ'); // ❌ 编译错误:类型'"XYZ"'不能赋给类型'"ABC"'
    log(ADMIN, 'GGG'); // ❌ 编译错误:类型'"GGG"'不能赋给类型'"ABC"'

    log(MODERATOR, 'ABC'); // ✅ 编译通过
    log(MODERATOR, 'XYZ'); // ✅ 编译通过
    log(MODERATOR, 'GGG'); // ❌ 编译错误
}

方式二:直接利用类型推断(无需泛型User)

如果不需要复用User类型,可以直接定义常量并让TypeScript自动推断完整类型,再通过泛型函数提取sites元素类型:

type Site = 'ABC' | 'XYZ';

// 定义用户常量,用as const固定数组元素的字面量类型
const ADMIN = {
    email: 'admin@gmail.com',
    sites: ['ABC'] as const,
} as const;

const MODERATOR = {
    email: 'mod@gmail.com',
    sites: ['ABC', 'XYZ'] as const,
} as const;

// 泛型log函数,约束第一个参数结构,提取其sites元素类型作为第二个参数类型
function log<U extends { sites: readonly Site[] }>(user: U, site: U['sites'][number]): void {
    console.log(`${user.email}/${site}`);
}

export function test(): void {
    log(ADMIN, 'ABC'); // ✅ 编译通过
    log(ADMIN, 'XYZ'); // ❌ 编译错误
    log(ADMIN, 'GGG'); // ❌ 编译错误
}

核心要点

  1. 避免类型拓宽:使用as const固定数组元素的字面量类型,防止TypeScript将其拓宽为Site[]。
  2. 泛型提取类型:通过泛型函数捕获第一个参数的具体类型,再用U['sites'][number]提取其sites数组的元素类型,作为第二个参数的约束。
  3. 类型约束保留:使用satisfies或直接推断类型,确保用户常量符合业务类型要求的同时,保留具体的元素类型信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:27:28