2 Object.defineProperty(exports, "__esModule", { value: true });
3 const ts = require("typescript");
4 const type_1 = require("../typeguard/type");
5 const util_1 = require("./util");
6 const node_1 = require("../typeguard/node");
7 function isEmptyObjectType(type) {
8 if (type_1.isObjectType(type) &&
9 type.objectFlags & ts.ObjectFlags.Anonymous &&
10 type.getProperties().length === 0 &&
11 type.getCallSignatures().length === 0 &&
12 type.getConstructSignatures().length === 0 &&
13 type.getStringIndexType() === undefined &&
14 type.getNumberIndexType() === undefined) {
15 const baseTypes = type.getBaseTypes();
16 return baseTypes === undefined || baseTypes.every(isEmptyObjectType);
20 exports.isEmptyObjectType = isEmptyObjectType;
21 function removeOptionalityFromType(checker, type) {
22 if (!containsTypeWithFlag(type, ts.TypeFlags.Undefined))
24 const allowsNull = containsTypeWithFlag(type, ts.TypeFlags.Null);
25 type = checker.getNonNullableType(type);
26 return allowsNull ? checker.getNullableType(type, ts.TypeFlags.Null) : type;
28 exports.removeOptionalityFromType = removeOptionalityFromType;
29 function containsTypeWithFlag(type, flag) {
30 for (const t of unionTypeParts(type))
31 if (util_1.isTypeFlagSet(t, flag))
35 function isTypeAssignableToNumber(checker, type) {
36 return isTypeAssignableTo(checker, type, ts.TypeFlags.NumberLike);
38 exports.isTypeAssignableToNumber = isTypeAssignableToNumber;
39 function isTypeAssignableToString(checker, type) {
40 return isTypeAssignableTo(checker, type, ts.TypeFlags.StringLike);
42 exports.isTypeAssignableToString = isTypeAssignableToString;
43 function isTypeAssignableTo(checker, type, flags) {
44 flags |= ts.TypeFlags.Any;
45 let typeParametersSeen;
46 return (function check(t) {
47 if (type_1.isTypeParameter(t) && t.symbol !== undefined && t.symbol.declarations !== undefined) {
48 if (typeParametersSeen === undefined) {
49 typeParametersSeen = new Set([t]);
51 else if (!typeParametersSeen.has(t)) {
52 typeParametersSeen.add(t);
57 const declaration = t.symbol.declarations[0];
58 if (declaration.constraint === undefined)
60 return check(checker.getTypeFromTypeNode(declaration.constraint));
62 if (type_1.isUnionType(t))
63 return t.types.every(check);
64 if (type_1.isIntersectionType(t))
65 return t.types.some(check);
66 return util_1.isTypeFlagSet(t, flags);
69 function getCallSignaturesOfType(type) {
70 if (type_1.isUnionType(type)) {
71 const signatures = [];
72 for (const t of type.types)
73 signatures.push(...getCallSignaturesOfType(t));
76 if (type_1.isIntersectionType(type)) {
78 for (const t of type.types) {
79 const sig = getCallSignaturesOfType(t);
80 if (sig.length !== 0) {
81 if (signatures !== undefined)
86 return signatures === undefined ? [] : signatures;
88 return type.getCallSignatures();
90 exports.getCallSignaturesOfType = getCallSignaturesOfType;
91 function unionTypeParts(type) {
92 return type_1.isUnionType(type) ? type.types : [type];
94 exports.unionTypeParts = unionTypeParts;
95 function intersectionTypeParts(type) {
96 return type_1.isIntersectionType(type) ? type.types : [type];
98 exports.intersectionTypeParts = intersectionTypeParts;
99 function someTypePart(type, predicate, cb) {
100 return predicate(type) ? type.types.some(cb) : cb(type);
102 exports.someTypePart = someTypePart;
103 function isThenableType(checker, node, type = checker.getTypeAtLocation(node)) {
104 for (const ty of unionTypeParts(checker.getApparentType(type))) {
105 const then = ty.getProperty('then');
106 if (then === undefined)
108 const thenType = checker.getTypeOfSymbolAtLocation(then, node);
109 for (const t of unionTypeParts(thenType))
110 for (const signature of t.getCallSignatures())
111 if (signature.parameters.length !== 0 && isCallback(checker, signature.parameters[0], node))
116 exports.isThenableType = isThenableType;
117 function isCallback(checker, param, node) {
118 let type = checker.getApparentType(checker.getTypeOfSymbolAtLocation(param, node));
119 if (param.valueDeclaration.dotDotDotToken) {
120 type = type.getNumberIndexType();
121 if (type === undefined)
124 for (const t of unionTypeParts(type))
125 if (t.getCallSignatures().length !== 0)
129 function isFalsyType(type) {
130 if (type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.Void))
132 if (type_1.isLiteralType(type))
134 return isBooleanLiteralType(type, false);
136 exports.isFalsyType = isFalsyType;
137 function isBooleanLiteralType(type, literal) {
138 return util_1.isTypeFlagSet(type, ts.TypeFlags.BooleanLiteral) &&
139 type.intrinsicName === (literal ? 'true' : 'false');
141 exports.isBooleanLiteralType = isBooleanLiteralType;
142 function getPropertyOfType(type, name) {
143 if (!name.startsWith('__'))
144 return type.getProperty(name);
145 return type.getProperties().find((s) => s.escapedName === name);
147 exports.getPropertyOfType = getPropertyOfType;
148 function isPropertyReadonlyInType(type, name, checker) {
149 let seenProperty = false;
150 let seenReadonlySignature = false;
151 for (const t of unionTypeParts(type)) {
152 if (getPropertyOfType(t, name) === undefined) {
153 const index = (util_1.isNumericPropertyName(name) ? checker.getIndexInfoOfType(t, ts.IndexKind.Number) : undefined) ||
154 checker.getIndexInfoOfType(t, ts.IndexKind.String);
155 if (index !== undefined && index.isReadonly) {
158 seenReadonlySignature = true;
161 else if (seenReadonlySignature || isReadonlyPropertyIntersection(t, name, checker)) {
170 exports.isPropertyReadonlyInType = isPropertyReadonlyInType;
171 function isReadonlyPropertyIntersection(type, name, checker) {
172 return someTypePart(type, type_1.isIntersectionType, (t) => {
173 const prop = getPropertyOfType(t, name);
174 if (prop === undefined)
176 if (prop.flags & ts.SymbolFlags.Transient) {
177 if (/^(?:[1-9]\d*|0)$/.test(name) && type_1.isTupleTypeReference(t))
178 return t.target.readonly;
179 switch (isReadonlyPropertyFromMappedType(t, name, checker)) {
187 return (util_1.isSymbolFlagSet(prop, ts.SymbolFlags.ValueModule) ||
188 symbolHasReadonlyDeclaration(prop, checker));
191 function isReadonlyPropertyFromMappedType(type, name, checker) {
192 if (!type_1.isObjectType(type) || !util_1.isObjectFlagSet(type, ts.ObjectFlags.Mapped))
194 const declaration = type.symbol.declarations[0];
195 if (declaration.readonlyToken !== undefined && !/^__@[^@]+$/.test(name))
196 return declaration.readonlyToken.kind !== ts.SyntaxKind.MinusToken;
197 return isPropertyReadonlyInType(type.modifiersType, name, checker);
199 function symbolHasReadonlyDeclaration(symbol, checker) {
200 return (symbol.flags & ts.SymbolFlags.Accessor) === ts.SymbolFlags.GetAccessor ||
201 symbol.declarations !== undefined &&
202 symbol.declarations.some((node) => util_1.isModifierFlagSet(node, ts.ModifierFlags.Readonly) ||
203 node_1.isVariableDeclaration(node) && util_1.isNodeFlagSet(node.parent, ts.NodeFlags.Const) ||
204 node_1.isCallExpression(node) && util_1.isReadonlyAssignmentDeclaration(node, checker) ||
205 node_1.isEnumMember(node) ||
206 (node_1.isPropertyAssignment(node) || node_1.isShorthandPropertyAssignment(node)) && util_1.isInConstContext(node.parent));
208 exports.symbolHasReadonlyDeclaration = symbolHasReadonlyDeclaration;
209 function getPropertyNameFromType(type) {
210 if (type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) {
211 const value = String(type.value);
212 return { displayName: value, symbolName: ts.escapeLeadingUnderscores(value) };
214 if (type_1.isUniqueESSymbolType(type))
216 displayName: `[${type.symbol ? type.symbol.name : type.escapedName.replace(/^__@|@\d+$/g, '')}]`,
217 symbolName: type.escapedName,
220 exports.getPropertyNameFromType = getPropertyNameFromType;
221 function getConstructorTypeOfClassLikeDeclaration(node, checker) {
222 return checker.getDeclaredTypeOfSymbol(node.name !== undefined ? checker.getSymbolAtLocation(node.name) : checker.getTypeAtLocation(node).symbol);
224 exports.getConstructorTypeOfClassLikeDeclaration = getConstructorTypeOfClassLikeDeclaration;
225 function getInstanceTypeOfClassLikeDeclaration(node, checker) {
226 return node.kind === ts.SyntaxKind.ClassDeclaration
227 ? checker.getTypeAtLocation(node)
228 : checker.getTypeOfSymbolAtLocation(checker.getTypeAtLocation(node).getProperty('prototype'), node);
230 exports.getInstanceTypeOfClassLikeDeclaration = getInstanceTypeOfClassLikeDeclaration;
231 function getIteratorYieldResultFromIteratorResult(type, node, checker) {
232 return type_1.isUnionType(type) && type.types.find((t) => {
233 const done = t.getProperty('done');
234 return done !== undefined &&
235 isBooleanLiteralType(removeOptionalityFromType(checker, checker.getTypeOfSymbolAtLocation(done, node)), false);
238 exports.getIteratorYieldResultFromIteratorResult = getIteratorYieldResultFromIteratorResult;