TypeScript ``` [编译器API] 函数,用于检查一个类是否实现了接口 ```

eqzww0vc  于 4个月前  发布在  TypeScript
关注(0)|答案(3)|浏览(63)

搜索词

编译器API, InterfaceDeclaration, ClassDeclaration, Checker

建议

一个函数,用于检查 ClassDeclaration 是否实现了 InterfaceDeclaration

用例

你好,我想使用编译器API检查 a.ts 文件中的 ClassDeclaration 是否实现了 b.ts 文件中的 InterfaceDeclaration。但是我找不到这样的方法或函数。

示例

function isClassImplementInterface(
  ts.ClassDeclaration: classDeclaration,
  ts.InterfaceDeclaration: interfaceDeclaration
): boolean {
  // return true if classDeclaration implements interfaceDeclaration correctly
}

检查清单

我的建议满足以下准则:

  • 这不会对现有的TypeScript/JavaScript代码造成破坏性改变
  • 这不会改变现有JavaScript代码的运行时行为
  • 这可以在不根据表达式的类型生成不同的JS的情况下实现
  • 这不是一个运行时特性(例如库功能、带有JavaScript输出的非ECMAScript语法等)
  • 这个特性会与 TypeScript's Design Goals 的其他部分保持一致。
kqhtkvqz

kqhtkvqz1#

我认为这不应该成为公共API的一部分。API的表面积越大,TS团队需要维护的工作就越多。
当前的API提供了编写自己的实用函数所需的一切(未经测试,但应该可以工作):

function classImplementsInterface(classDeclaration: ts.ClassDeclaration, interfaceDeclaration: ts.InterfaceDeclaration, checker: ts.TypeChecker) {
    const heritageClause = classDeclaration.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ImplementsKeyword);
    if (!heritageClause) {
        return false;
    }
    const interfaceSymbol = checker.getSymbolAtLocation(interfaceDeclaration.name);
    if (!interfaceSymbol) {
        return false;
    }
    return heritageClause.types.some((baseType) => {
        let symbol = checker.getSymbolAtLocation(baseType);
        if (symbol && symbol.flags & ts.SymbolFlags.Alias) {
            symbol = checker.getAliasedSymbol(symbol);
        }
        return symbol === interfaceSymbol;
    });
}

如果您需要了解它的作用,请在这里提问。
如果我需要这样的功能,我通常会将其放入我的实用程序库tsutils中,该库已经包含了许多有用(且大部分未记录)的函数。

bvjveswy

bvjveswy2#

哇,非常感谢!上述代码将对我有很大帮助。
我会尝试根据您的指导编写一个实用程序代码。
谢谢!:D

wyyhbhjk

wyyhbhjk3#

@ajafff 我测试了上面的代码,它运行良好,但我修复了一个部分。
getSymbolAtLocation(baseType)getSymbolAtLocation(baseType.expression)

function classImplementsInterface(classDeclaration: ts.ClassDeclaration, interfaceDeclaration: ts.InterfaceDeclaration, checker: ts.TypeChecker) {
    const heritageClause = classDeclaration.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ImplementsKeyword);
    if (!heritageClause) {
        return false;
    }
    const interfaceSymbol = checker.getSymbolAtLocation(interfaceDeclaration.name);
    if (!interfaceSymbol) {
        return false;
    }
    return heritageClause.types.some((baseType) => {
        let symbol = checker.getSymbolAtLocation(baseType.expression);
        if (symbol && symbol.flags & ts.SymbolFlags.Alias) {
            symbol = checker.getAliasedSymbol(symbol);
        }
        return symbol === interfaceSymbol;
    });
}

希望我做对了:D
谢谢!

相关问题