UNPKG

5.01 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 utils_1 = require("@typescript-eslint/utils");
23const tsutils = __importStar(require("tsutils"));
24const ts = __importStar(require("typescript"));
25const util = __importStar(require("../util"));
26exports.default = util.createRule({
27 name: 'non-nullable-type-assertion-style',
28 meta: {
29 docs: {
30 description: 'Prefers a non-null assertion over explicit type cast when possible',
31 recommended: false,
32 requiresTypeChecking: true,
33 suggestion: true,
34 },
35 fixable: 'code',
36 messages: {
37 preferNonNullAssertion: 'Use a ! assertion to more succinctly remove null and undefined from the type.',
38 },
39 schema: [],
40 type: 'suggestion',
41 },
42 defaultOptions: [],
43 create(context) {
44 const parserServices = util.getParserServices(context);
45 const checker = parserServices.program.getTypeChecker();
46 const sourceCode = context.getSourceCode();
47 const getTypesIfNotLoose = (node) => {
48 const type = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
49 if (tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) {
50 return undefined;
51 }
52 return tsutils.unionTypeParts(type);
53 };
54 const couldBeNullish = (type) => {
55 if (type.flags & ts.TypeFlags.TypeParameter) {
56 const constraint = type.getConstraint();
57 return constraint == null || couldBeNullish(constraint);
58 }
59 else if (tsutils.isUnionType(type)) {
60 for (const part of type.types) {
61 if (couldBeNullish(part)) {
62 return true;
63 }
64 }
65 return false;
66 }
67 else {
68 return ((type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0);
69 }
70 };
71 const sameTypeWithoutNullish = (assertedTypes, originalTypes) => {
72 const nonNullishOriginalTypes = originalTypes.filter(type => (type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) === 0);
73 if (nonNullishOriginalTypes.length === originalTypes.length) {
74 return false;
75 }
76 for (const assertedType of assertedTypes) {
77 if (couldBeNullish(assertedType) ||
78 !nonNullishOriginalTypes.includes(assertedType)) {
79 return false;
80 }
81 }
82 for (const originalType of nonNullishOriginalTypes) {
83 if (!assertedTypes.includes(originalType)) {
84 return false;
85 }
86 }
87 return true;
88 };
89 const isConstAssertion = (node) => {
90 return (node.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
91 node.typeAnnotation.typeName.type === utils_1.AST_NODE_TYPES.Identifier &&
92 node.typeAnnotation.typeName.name === 'const');
93 };
94 return {
95 'TSAsExpression, TSTypeAssertion'(node) {
96 if (isConstAssertion(node)) {
97 return;
98 }
99 const originalTypes = getTypesIfNotLoose(node.expression);
100 if (!originalTypes) {
101 return;
102 }
103 const assertedTypes = getTypesIfNotLoose(node.typeAnnotation);
104 if (!assertedTypes) {
105 return;
106 }
107 if (sameTypeWithoutNullish(assertedTypes, originalTypes)) {
108 context.report({
109 fix(fixer) {
110 return fixer.replaceText(node, `${sourceCode.getText(node.expression)}!`);
111 },
112 messageId: 'preferNonNullAssertion',
113 node,
114 });
115 }
116 },
117 };
118 },
119});
120//# sourceMappingURL=non-nullable-type-assertion-style.js.map
\No newline at end of file