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

如何使用TypeScript编译器API检查类型是否继承另一种类型

问题:TypeScript类型字面量的继承检查失败

我正在开发一款工具,用于将TypeScript定义转换为干净的d.ts文件(而非保留用于调整各类结构的辅助类型)。暂不考虑递归的情况下,工具运行效果良好,但存在一个棘手的限制:我无法检查一种类型字面量是否继承另一种类型,我本以为这是件简单的事。

我尝试了以下代码及多种变体(包括省略getTypeAtLocation):

import ts from 'typescript';

const program = ts.createProgram([], {})
const checker = program.getTypeChecker();

// { result: any }
const node1 = ts.factory.createTypeLiteralNode([
  ts.factory.createPropertySignature([], "result", undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))
]);


// { something: any }
const node2 = ts.factory.createTypeLiteralNode([
   ts.factory.createPropertySignature([], "something", undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))
 ]);

checker.isTypeAssignableTo(
  checker.getTypeAtLocation(node1),
  checker.getTypeAtLocation(node2)
)

isTypeAssignableTo在检查false/true或string/number这类基础类型时有效,但对类型字面量无效。我可能犯了某个低级错误,要么是解决方案显而易见,要么是这件事本身难度极高不应尝试。


解决方案

问题核心在于直接创建的类型字面量节点没有经过TypeScript的类型绑定阶段,getTypeAtLocation无法正确解析出完整的类型信息。TypeScript的类型检查器需要在有上下文的环境中工作,孤立的AST节点不会被完全处理。

解决步骤

  1. 创建包含类型字面量的完整源文件:
    把类型字面量包装在一个完整的TypeScript源文件中,让程序能正确解析和绑定这些类型。
  2. 通过符号获取合法类型对象:
    从源文件中提取类型的符号,再通过检查器获取对应的类型对象,这样isTypeAssignableTo才能正常工作。

修改后的代码示例

import ts from 'typescript';

// 创建临时源文件,包含两个类型别名
const sourceCode = `
type Type1 = { result: any };
type Type2 = { something: any };
`;

// 创建包含该源文件的程序
const program = ts.createProgram(
  ['temp.ts'],
  {},
  {
    getSourceFile(fileName, languageVersion) {
      if (fileName === 'temp.ts') {
        return ts.createSourceFile(
          fileName,
          sourceCode,
          ts.ScriptTarget.Latest,
          true
        );
      }
      return undefined;
    }
  }
);

const checker = program.getTypeChecker();
const sourceFile = program.getSourceFile('temp.ts')!;

// 找到两个类型别名节点
const typeAliases = sourceFile.statements.filter(
  ts.isTypeAliasDeclaration
) as ts.TypeAliasDeclaration[];
const type1 = checker.getTypeFromTypeNode(typeAliases[0].type);
const type2 = checker.getTypeFromTypeNode(typeAliases[1].type);

// 现在可正确检查可赋值性(此处返回false,因两个类型结构不匹配)
console.log(checker.isTypeAssignableTo(type1, type2)); // false

// 测试继承场景:Type3 扩展 Type1
const sourceCodeWithExtends = `
type Type1 = { result: any };
type Type3 = Type1 & { extra: string };
`;
// 重复上述步骤获取Type1和Type3的类型后
// checker.isTypeAssignableTo(type3, type1) 会返回true

额外说明

  • TypeScript中“类型字面量继承”本质是结构类型的可赋值性,若要检查A是否是B的子类型(即A可赋值给B),isTypeAssignableTo是正确API,但必须确保类型对象经过完整绑定。
  • 若要检查显式继承关系(比如通过extends关键字),则需遍历AST节点,检查类型字面量的heritageClauses属性,而非依赖类型检查器的可赋值性方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:42:39