UNPKG

5.27 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21Object.defineProperty(exports, "__esModule", { value: true });
22const tsutils = __importStar(require("tsutils"));
23const ts = __importStar(require("typescript"));
24const util = __importStar(require("../util"));
25const util_1 = require("../util");
26exports.default = util.createRule({
27 name: 'no-unnecessary-type-arguments',
28 meta: {
29 docs: {
30 description: 'Enforces that type arguments will not be used if not required',
31 recommended: false,
32 requiresTypeChecking: true,
33 },
34 fixable: 'code',
35 messages: {
36 unnecessaryTypeParameter: 'This is the default value for this type parameter, so it can be omitted.',
37 },
38 schema: [],
39 type: 'suggestion',
40 },
41 defaultOptions: [],
42 create(context) {
43 const parserServices = util.getParserServices(context);
44 const checker = parserServices.program.getTypeChecker();
45 function checkTSArgsAndParameters(esParameters, typeParameters) {
46 // Just check the last one. Must specify previous type parameters if the last one is specified.
47 const i = esParameters.params.length - 1;
48 const arg = esParameters.params[i];
49 const param = typeParameters[i];
50 if (!(param === null || param === void 0 ? void 0 : param.default)) {
51 return;
52 }
53 // TODO: would like checker.areTypesEquivalent. https://github.com/Microsoft/TypeScript/issues/13502
54 const defaultType = checker.getTypeAtLocation(param.default);
55 const argTsNode = parserServices.esTreeNodeToTSNodeMap.get(arg);
56 const argType = checker.getTypeAtLocation(argTsNode);
57 if (!argType.aliasSymbol && !defaultType.aliasSymbol) {
58 if (argType.flags !== defaultType.flags) {
59 return;
60 }
61 }
62 else if (argType.aliasSymbol !== defaultType.aliasSymbol ||
63 argType.aliasTypeArguments !== defaultType.aliasTypeArguments) {
64 return;
65 }
66 context.report({
67 node: arg,
68 messageId: 'unnecessaryTypeParameter',
69 fix: fixer => fixer.removeRange(i === 0
70 ? esParameters.range
71 : [esParameters.params[i - 1].range[1], arg.range[1]]),
72 });
73 }
74 return {
75 TSTypeParameterInstantiation(node) {
76 const expression = parserServices.esTreeNodeToTSNodeMap.get(node);
77 const typeParameters = getTypeParametersFromNode(expression, checker);
78 if (typeParameters) {
79 checkTSArgsAndParameters(node, typeParameters);
80 }
81 },
82 };
83 },
84});
85function getTypeParametersFromNode(node, checker) {
86 if (ts.isExpressionWithTypeArguments(node)) {
87 return getTypeParametersFromType(node.expression, checker);
88 }
89 if (ts.isTypeReferenceNode(node)) {
90 return getTypeParametersFromType(node.typeName, checker);
91 }
92 if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
93 return getTypeParametersFromCall(node, checker);
94 }
95 return undefined;
96}
97function getTypeParametersFromType(type, checker) {
98 const symAtLocation = checker.getSymbolAtLocation(type);
99 if (!symAtLocation) {
100 return undefined;
101 }
102 const sym = getAliasedSymbol(symAtLocation, checker);
103 const declarations = sym.getDeclarations();
104 if (!declarations) {
105 return undefined;
106 }
107 return (0, util_1.findFirstResult)(declarations, decl => ts.isClassLike(decl) ||
108 ts.isTypeAliasDeclaration(decl) ||
109 ts.isInterfaceDeclaration(decl)
110 ? decl.typeParameters
111 : undefined);
112}
113function getTypeParametersFromCall(node, checker) {
114 const sig = checker.getResolvedSignature(node);
115 const sigDecl = sig === null || sig === void 0 ? void 0 : sig.getDeclaration();
116 if (!sigDecl) {
117 return ts.isNewExpression(node)
118 ? getTypeParametersFromType(node.expression, checker)
119 : undefined;
120 }
121 return sigDecl.typeParameters;
122}
123function getAliasedSymbol(symbol, checker) {
124 return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias)
125 ? checker.getAliasedSymbol(symbol)
126 : symbol;
127}
128//# sourceMappingURL=no-unnecessary-type-arguments.js.map
\No newline at end of file