2 Object.defineProperty(exports, "__esModule", { value: true });
\r
3 exports.getBaseClassMemberOfClassElement = exports.getIteratorYieldResultFromIteratorResult = exports.getInstanceTypeOfClassLikeDeclaration = exports.getConstructorTypeOfClassLikeDeclaration = exports.getSymbolOfClassLikeDeclaration = exports.getPropertyNameFromType = exports.symbolHasReadonlyDeclaration = exports.isPropertyReadonlyInType = exports.getWellKnownSymbolPropertyOfType = exports.getPropertyOfType = exports.isBooleanLiteralType = exports.isFalsyType = exports.isThenableType = exports.someTypePart = exports.intersectionTypeParts = exports.unionTypeParts = exports.getCallSignaturesOfType = exports.isTypeAssignableToString = exports.isTypeAssignableToNumber = exports.isOptionalChainingUndefinedMarkerType = exports.removeOptionalChainingUndefinedMarkerType = exports.removeOptionalityFromType = exports.isEmptyObjectType = void 0;
\r
4 const ts = require("typescript");
\r
5 const type_1 = require("../typeguard/type");
\r
6 const util_1 = require("./util");
\r
7 const node_1 = require("../typeguard/node");
\r
8 function isEmptyObjectType(type) {
\r
9 if (type_1.isObjectType(type) &&
\r
10 type.objectFlags & ts.ObjectFlags.Anonymous &&
\r
11 type.getProperties().length === 0 &&
\r
12 type.getCallSignatures().length === 0 &&
\r
13 type.getConstructSignatures().length === 0 &&
\r
14 type.getStringIndexType() === undefined &&
\r
15 type.getNumberIndexType() === undefined) {
\r
16 const baseTypes = type.getBaseTypes();
\r
17 return baseTypes === undefined || baseTypes.every(isEmptyObjectType);
\r
21 exports.isEmptyObjectType = isEmptyObjectType;
\r
22 function removeOptionalityFromType(checker, type) {
\r
23 if (!containsTypeWithFlag(type, ts.TypeFlags.Undefined))
\r
25 const allowsNull = containsTypeWithFlag(type, ts.TypeFlags.Null);
\r
26 type = checker.getNonNullableType(type);
\r
27 return allowsNull ? checker.getNullableType(type, ts.TypeFlags.Null) : type;
\r
29 exports.removeOptionalityFromType = removeOptionalityFromType;
\r
30 function containsTypeWithFlag(type, flag) {
\r
31 for (const t of unionTypeParts(type))
\r
32 if (util_1.isTypeFlagSet(t, flag))
\r
36 function removeOptionalChainingUndefinedMarkerType(checker, type) {
\r
37 if (!type_1.isUnionType(type))
\r
38 return isOptionalChainingUndefinedMarkerType(checker, type) ? type.getNonNullableType() : type;
\r
40 let containsUndefinedMarker = false;
\r
41 for (const t of type.types) {
\r
42 if (isOptionalChainingUndefinedMarkerType(checker, t)) {
\r
43 containsUndefinedMarker = true;
\r
49 return containsUndefinedMarker
\r
50 ? checker.getNullableType(type.getNonNullableType(), flags)
\r
53 exports.removeOptionalChainingUndefinedMarkerType = removeOptionalChainingUndefinedMarkerType;
\r
54 function isOptionalChainingUndefinedMarkerType(checker, t) {
\r
55 return util_1.isTypeFlagSet(t, ts.TypeFlags.Undefined) && checker.getNullableType(t.getNonNullableType(), ts.TypeFlags.Undefined) !== t;
\r
57 exports.isOptionalChainingUndefinedMarkerType = isOptionalChainingUndefinedMarkerType;
\r
58 function isTypeAssignableToNumber(checker, type) {
\r
59 return isTypeAssignableTo(checker, type, ts.TypeFlags.NumberLike);
\r
61 exports.isTypeAssignableToNumber = isTypeAssignableToNumber;
\r
62 function isTypeAssignableToString(checker, type) {
\r
63 return isTypeAssignableTo(checker, type, ts.TypeFlags.StringLike);
\r
65 exports.isTypeAssignableToString = isTypeAssignableToString;
\r
66 function isTypeAssignableTo(checker, type, flags) {
\r
67 flags |= ts.TypeFlags.Any;
\r
68 let typeParametersSeen;
\r
69 return (function check(t) {
\r
70 if (type_1.isTypeParameter(t) && t.symbol !== undefined && t.symbol.declarations !== undefined) {
\r
71 if (typeParametersSeen === undefined) {
\r
72 typeParametersSeen = new Set([t]);
\r
74 else if (!typeParametersSeen.has(t)) {
\r
75 typeParametersSeen.add(t);
\r
80 const declaration = t.symbol.declarations[0];
\r
81 if (declaration.constraint === undefined)
\r
82 return true; // TODO really?
\r
83 return check(checker.getTypeFromTypeNode(declaration.constraint));
\r
85 if (type_1.isUnionType(t))
\r
86 return t.types.every(check);
\r
87 if (type_1.isIntersectionType(t))
\r
88 return t.types.some(check);
\r
89 return util_1.isTypeFlagSet(t, flags);
\r
92 function getCallSignaturesOfType(type) {
\r
93 if (type_1.isUnionType(type)) {
\r
94 const signatures = [];
\r
95 for (const t of type.types)
\r
96 signatures.push(...getCallSignaturesOfType(t));
\r
99 if (type_1.isIntersectionType(type)) {
\r
101 for (const t of type.types) {
\r
102 const sig = getCallSignaturesOfType(t);
\r
103 if (sig.length !== 0) {
\r
104 if (signatures !== undefined)
\r
105 return []; // if more than one type of the intersection has call signatures, none of them is useful for inference
\r
109 return signatures === undefined ? [] : signatures;
\r
111 return type.getCallSignatures();
\r
113 exports.getCallSignaturesOfType = getCallSignaturesOfType;
\r
114 /** Returns all types of a union type or an array containing `type` itself if it's no union type. */
\r
115 function unionTypeParts(type) {
\r
116 return type_1.isUnionType(type) ? type.types : [type];
\r
118 exports.unionTypeParts = unionTypeParts;
\r
119 /** Returns all types of a intersection type or an array containing `type` itself if it's no intersection type. */
\r
120 function intersectionTypeParts(type) {
\r
121 return type_1.isIntersectionType(type) ? type.types : [type];
\r
123 exports.intersectionTypeParts = intersectionTypeParts;
\r
124 function someTypePart(type, predicate, cb) {
\r
125 return predicate(type) ? type.types.some(cb) : cb(type);
\r
127 exports.someTypePart = someTypePart;
\r
128 function isThenableType(checker, node, type = checker.getTypeAtLocation(node)) {
\r
129 for (const ty of unionTypeParts(checker.getApparentType(type))) {
\r
130 const then = ty.getProperty('then');
\r
131 if (then === undefined)
\r
133 const thenType = checker.getTypeOfSymbolAtLocation(then, node);
\r
134 for (const t of unionTypeParts(thenType))
\r
135 for (const signature of t.getCallSignatures())
\r
136 if (signature.parameters.length !== 0 && isCallback(checker, signature.parameters[0], node))
\r
141 exports.isThenableType = isThenableType;
\r
142 function isCallback(checker, param, node) {
\r
143 let type = checker.getApparentType(checker.getTypeOfSymbolAtLocation(param, node));
\r
144 if (param.valueDeclaration.dotDotDotToken) {
\r
145 // unwrap array type of rest parameter
\r
146 type = type.getNumberIndexType();
\r
147 if (type === undefined)
\r
150 for (const t of unionTypeParts(type))
\r
151 if (t.getCallSignatures().length !== 0)
\r
155 /** Determine if a type is definitely falsy. This function doesn't unwrap union types. */
\r
156 function isFalsyType(type) {
\r
157 if (type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.Void))
\r
159 if (type_1.isLiteralType(type))
\r
160 return !type.value;
\r
161 return isBooleanLiteralType(type, false);
\r
163 exports.isFalsyType = isFalsyType;
\r
164 /** Determines whether the given type is a boolean literal type and matches the given boolean literal (true or false). */
\r
165 function isBooleanLiteralType(type, literal) {
\r
166 return util_1.isTypeFlagSet(type, ts.TypeFlags.BooleanLiteral) &&
\r
167 type.intrinsicName === (literal ? 'true' : 'false');
\r
169 exports.isBooleanLiteralType = isBooleanLiteralType;
\r
170 function getPropertyOfType(type, name) {
\r
171 if (!name.startsWith('__'))
\r
172 return type.getProperty(name);
\r
173 return type.getProperties().find((s) => s.escapedName === name);
\r
175 exports.getPropertyOfType = getPropertyOfType;
\r
176 function getWellKnownSymbolPropertyOfType(type, wellKnownSymbolName, checker) {
\r
177 const prefix = '__@' + wellKnownSymbolName;
\r
178 for (const prop of type.getProperties()) {
\r
179 if (!prop.name.startsWith(prefix))
\r
181 const globalSymbol = checker.getApparentType(checker.getTypeAtLocation(prop.valueDeclaration.name.expression)).symbol;
\r
182 if (prop.escapedName === getPropertyNameOfWellKnownSymbol(checker, globalSymbol, wellKnownSymbolName))
\r
187 exports.getWellKnownSymbolPropertyOfType = getWellKnownSymbolPropertyOfType;
\r
188 function getPropertyNameOfWellKnownSymbol(checker, symbolConstructor, symbolName) {
\r
189 const knownSymbol = symbolConstructor &&
\r
190 checker.getTypeOfSymbolAtLocation(symbolConstructor, symbolConstructor.valueDeclaration).getProperty(symbolName);
\r
191 const knownSymbolType = knownSymbol && checker.getTypeOfSymbolAtLocation(knownSymbol, knownSymbol.valueDeclaration);
\r
192 if (knownSymbolType && type_1.isUniqueESSymbolType(knownSymbolType))
\r
193 return knownSymbolType.escapedName;
\r
194 return ('__@' + symbolName);
\r
196 /** Determines if writing to a certain property of a given type is allowed. */
\r
197 function isPropertyReadonlyInType(type, name, checker) {
\r
198 let seenProperty = false;
\r
199 let seenReadonlySignature = false;
\r
200 for (const t of unionTypeParts(type)) {
\r
201 if (getPropertyOfType(t, name) === undefined) {
\r
202 // property is not present in this part of the union -> check for readonly index signature
\r
203 const index = (util_1.isNumericPropertyName(name) ? checker.getIndexInfoOfType(t, ts.IndexKind.Number) : undefined) ||
\r
204 checker.getIndexInfoOfType(t, ts.IndexKind.String);
\r
205 if (index !== undefined && index.isReadonly) {
\r
208 seenReadonlySignature = true;
\r
211 else if (seenReadonlySignature || isReadonlyPropertyIntersection(t, name, checker)) {
\r
215 seenProperty = true;
\r
220 exports.isPropertyReadonlyInType = isPropertyReadonlyInType;
\r
221 function isReadonlyPropertyIntersection(type, name, checker) {
\r
222 return someTypePart(type, type_1.isIntersectionType, (t) => {
\r
223 const prop = getPropertyOfType(t, name);
\r
224 if (prop === undefined)
\r
226 if (prop.flags & ts.SymbolFlags.Transient) {
\r
227 if (/^(?:[1-9]\d*|0)$/.test(name) && type_1.isTupleTypeReference(t))
\r
228 return t.target.readonly;
\r
229 switch (isReadonlyPropertyFromMappedType(t, name, checker)) {
\r
235 // `undefined` falls through
\r
239 // members of namespace import
\r
240 util_1.isSymbolFlagSet(prop, ts.SymbolFlags.ValueModule) ||
\r
241 // we unwrapped every mapped type, now we can check the actual declarations
\r
242 symbolHasReadonlyDeclaration(prop, checker));
\r
245 function isReadonlyPropertyFromMappedType(type, name, checker) {
\r
246 if (!type_1.isObjectType(type) || !util_1.isObjectFlagSet(type, ts.ObjectFlags.Mapped))
\r
248 const declaration = type.symbol.declarations[0];
\r
249 // well-known symbols are not affected by mapped types
\r
250 if (declaration.readonlyToken !== undefined && !/^__@[^@]+$/.test(name))
\r
251 return declaration.readonlyToken.kind !== ts.SyntaxKind.MinusToken;
\r
252 return isPropertyReadonlyInType(type.modifiersType, name, checker);
\r
254 function symbolHasReadonlyDeclaration(symbol, checker) {
\r
255 return (symbol.flags & ts.SymbolFlags.Accessor) === ts.SymbolFlags.GetAccessor ||
\r
256 symbol.declarations !== undefined &&
\r
257 symbol.declarations.some((node) => util_1.isModifierFlagSet(node, ts.ModifierFlags.Readonly) ||
\r
258 node_1.isVariableDeclaration(node) && util_1.isNodeFlagSet(node.parent, ts.NodeFlags.Const) ||
\r
259 node_1.isCallExpression(node) && util_1.isReadonlyAssignmentDeclaration(node, checker) ||
\r
260 node_1.isEnumMember(node) ||
\r
261 (node_1.isPropertyAssignment(node) || node_1.isShorthandPropertyAssignment(node)) && util_1.isInConstContext(node.parent));
\r
263 exports.symbolHasReadonlyDeclaration = symbolHasReadonlyDeclaration;
\r
264 /** Returns the the literal name or unique symbol name from a given type. Doesn't unwrap union types. */
\r
265 function getPropertyNameFromType(type) {
\r
266 // string or number literal. bigint is intentionally excluded
\r
267 if (type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) {
\r
268 const value = String(type.value);
\r
269 return { displayName: value, symbolName: ts.escapeLeadingUnderscores(value) };
\r
271 if (type_1.isUniqueESSymbolType(type))
\r
273 displayName: `[${type.symbol
\r
274 ? `${isKnownSymbol(type.symbol) ? 'Symbol.' : ''}${type.symbol.name}`
\r
275 : type.escapedName.replace(/^__@|@\d+$/g, '')}]`,
\r
276 symbolName: type.escapedName,
\r
279 exports.getPropertyNameFromType = getPropertyNameFromType;
\r
280 function isKnownSymbol(symbol) {
\r
281 return util_1.isSymbolFlagSet(symbol, ts.SymbolFlags.Property) &&
\r
282 symbol.valueDeclaration !== undefined &&
\r
283 node_1.isInterfaceDeclaration(symbol.valueDeclaration.parent) &&
\r
284 symbol.valueDeclaration.parent.name.text === 'SymbolConstructor' &&
\r
285 isGlobalDeclaration(symbol.valueDeclaration.parent);
\r
287 function isGlobalDeclaration(node) {
\r
288 return util_1.isNodeFlagSet(node.parent, ts.NodeFlags.GlobalAugmentation) || node_1.isSourceFile(node.parent) && !ts.isExternalModule(node.parent);
\r
290 function getSymbolOfClassLikeDeclaration(node, checker) {
\r
292 return checker.getSymbolAtLocation((_a = node.name) !== null && _a !== void 0 ? _a : util_1.getChildOfKind(node, ts.SyntaxKind.ClassKeyword));
\r
294 exports.getSymbolOfClassLikeDeclaration = getSymbolOfClassLikeDeclaration;
\r
295 function getConstructorTypeOfClassLikeDeclaration(node, checker) {
\r
296 return node.kind === ts.SyntaxKind.ClassExpression
\r
297 ? checker.getTypeAtLocation(node)
\r
298 : checker.getTypeOfSymbolAtLocation(getSymbolOfClassLikeDeclaration(node, checker), node);
\r
300 exports.getConstructorTypeOfClassLikeDeclaration = getConstructorTypeOfClassLikeDeclaration;
\r
301 function getInstanceTypeOfClassLikeDeclaration(node, checker) {
\r
302 return node.kind === ts.SyntaxKind.ClassDeclaration
\r
303 ? checker.getTypeAtLocation(node)
\r
304 : checker.getDeclaredTypeOfSymbol(getSymbolOfClassLikeDeclaration(node, checker));
\r
306 exports.getInstanceTypeOfClassLikeDeclaration = getInstanceTypeOfClassLikeDeclaration;
\r
307 function getIteratorYieldResultFromIteratorResult(type, node, checker) {
\r
308 return type_1.isUnionType(type) && type.types.find((t) => {
\r
309 const done = t.getProperty('done');
\r
310 return done !== undefined &&
\r
311 isBooleanLiteralType(removeOptionalityFromType(checker, checker.getTypeOfSymbolAtLocation(done, node)), false);
\r
314 exports.getIteratorYieldResultFromIteratorResult = getIteratorYieldResultFromIteratorResult;
\r
315 /** Lookup the declaration of a class member in the super class. */
\r
316 function getBaseClassMemberOfClassElement(node, checker) {
\r
317 if (!node_1.isClassLikeDeclaration(node.parent))
\r
319 const base = util_1.getBaseOfClassLikeExpression(node.parent);
\r
320 if (base === undefined)
\r
322 const name = util_1.getSingleLateBoundPropertyNameOfPropertyName(node.name, checker);
\r
323 if (name === undefined)
\r
325 const baseType = checker.getTypeAtLocation(util_1.hasModifier(node.modifiers, ts.SyntaxKind.StaticKeyword)
\r
328 return getPropertyOfType(baseType, name.symbolName);
\r
330 exports.getBaseClassMemberOfClassElement = getBaseClassMemberOfClassElement;
\r
331 //# sourceMappingURL=type.js.map