如何在typescript-eslint自定义规则中验证变量的类型

mqkwyuun  于 2023-05-19  发布在  TypeScript
关注(0)|答案(1)|浏览(184)

我正在尝试编写一个自定义的typescript-eslint规则,其中我需要确保节点的被调用方对象具有特定的Type,这里我将其称为MyType。所以我使用的是typescript-eslint的CallExpression,如下面的代码所示
源代码:

interface MyType {
   ...
}

const someVariable: MyType = ...;

自定义typescript-eslint规则:

export const rule = createRule({
  name: 'some-name',
  meta: {
    type: 'problem',
    docs: {
      description: 'description',
      recommended: 'error',
    },
    schema: [],
    messages,
  },
  defaultOptions: [],
  create: (context) => {
    return {
      CallExpression(node: TSESTree.CallExpression) {
        const services = ESLintUtils.getParserServices(context);
        const checker = services.program.getTypeChecker();

        const callee = node.callee;
        const object = callee.type === 'MemberExpression' ? callee.object : null;

        if (object === null) {
          return;
        }

        const type = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(object));

        const isMyType = (
          object.type === 'Identifier' &&
          (type as any)?.symbol?.escapedName === 'MyType'
        );

        if (isMyType) {
          [... do stuff here]
        }
      },
    };
  },
});

然而,我的问题是符号或escapedName未定义,因此它不等于'MyType'。有没有更好的方法来检查被调用方的对象是否属于特定类型?

e4yzc0pl

e4yzc0pl1#

根据评论,这个问题可以完全在TS模板文字中解决,而不需要ESLint规则。对于无效的调用,错误也会出现在编译时。TS模板文字允许TS理解可静态分析的字符串的构造。
这里的一个限制是第一个参数必须直接提供,即它不能通过由其他字符串组成的变量来构造。但这也适用于埃斯林特的方式。

type StringToTuple<S extends any, A extends any[] = []> =
  S extends `${string}{}${infer Rest}`
    ? StringToTuple<Rest, [...A, any]>
    : A;

const format = <S extends string>(inputStr: S, ...args: StringToTuple<S>): string  => {
  return inputStr // Do actual logic here
}

const result1 = format('something {} something {}', 10, 'two');  // OK
const result2 = format('something {} something {}', 'one', 'two', 'three');  // Compile error
const result3 = format('something {} something {} something {}', 'one', 'two', 'three');  // OK

相关问题