Comparing version 3.10.0 to 3.11.0
@@ -0,1 +1,20 @@ | ||
# 3.11.0 | ||
**Features:** | ||
* typeguards: `isNumericOrStringLikeLiteral`, `isTupleTypeReference` | ||
* `intersectionTypeParts` as counterpart to `unionTypeParts` | ||
* `someTypePart` to execute a callback for each union or intersection constituent until the callback returns true | ||
* `getPropertyOfType` looks up a property by its escaped name | ||
* `isPropertyReadonlyInType` determines whether a property in a given type cannot be written to | ||
* `symbolHasReadonlyDeclaration` determines if a Symbol has any readonly or constant declaration | ||
* `isNumericPropertyName` determines whether a property name would match an index signature | ||
* `isBindableObjectDefinePropertyCall` returns true for statically analyzable forms of `Object.defineProperty(o, 'p', {value, writable})` | ||
* `isReadonlyAssignmentDeclaration` determines whether an `Object.defineProperty` call is known to result in a readonly property | ||
* `getLateBoundPropertyNames` returns all known property names of an expression | ||
* `getPropertyNameFromType` extracts the property name of literal types | ||
* `isWellKnownSymbolLiterally` to recognize expressions in the form of `Symbol.<name>` | ||
* `getPropertyNameOfWellKnownSymbol` returns the escaped name for a well known symbol literal | ||
* `unwrapParentheses` returns the first child expression that is not a `ParenthesizedExpression` | ||
# 3.10.0 | ||
@@ -2,0 +21,0 @@ |
{ | ||
"name": "tsutils", | ||
"version": "3.10.0", | ||
"version": "3.11.0", | ||
"description": "utilities for working with typescript's AST", | ||
@@ -50,6 +50,6 @@ "scripts": { | ||
"ttypescript": "^1.5.5", | ||
"typescript": "^3.4.1" | ||
"typescript": "^3.4.5" | ||
}, | ||
"peerDependencies": { | ||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev" | ||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev" | ||
}, | ||
@@ -56,0 +56,0 @@ "dependencies": { |
@@ -108,2 +108,3 @@ import * as ts from 'typescript'; | ||
export declare function isNumericLiteral(node: ts.Node): node is ts.NumericLiteral; | ||
export declare function isNumericOrStringLikeLiteral(node: ts.Node): node is ts.NumericLiteral | ts.StringLiteral | ts.NoSubstitutionTemplateLiteral; | ||
export declare function isObjectBindingPattern(node: ts.Node): node is ts.ObjectBindingPattern; | ||
@@ -110,0 +111,0 @@ export declare function isObjectLiteralExpression(node: ts.Node): node is ts.ObjectLiteralExpression; |
@@ -509,2 +509,13 @@ "use strict"; | ||
exports.isNumericLiteral = isNumericLiteral; | ||
function isNumericOrStringLikeLiteral(node) { | ||
switch (node.kind) { | ||
case ts.SyntaxKind.StringLiteral: | ||
case ts.SyntaxKind.NumericLiteral: | ||
case ts.SyntaxKind.NoSubstitutionTemplateLiteral: | ||
return true; | ||
default: | ||
return false; | ||
} | ||
} | ||
exports.isNumericOrStringLikeLiteral = isNumericOrStringLikeLiteral; | ||
function isObjectBindingPattern(node) { | ||
@@ -511,0 +522,0 @@ return node.kind === ts.SyntaxKind.ObjectBindingPattern; |
export * from '../2.9/type'; | ||
import * as ts from 'typescript'; | ||
export declare function isTupleType(type: ts.Type): type is ts.TupleType; | ||
export declare function isTupleTypeReference(type: ts.Type): type is ts.TypeReference & { | ||
target: ts.TupleType; | ||
}; |
@@ -6,2 +6,3 @@ "use strict"; | ||
const ts = require("typescript"); | ||
const _3_2_1 = require("../3.2"); | ||
function isTupleType(type) { | ||
@@ -11,1 +12,5 @@ return (type.flags & ts.TypeFlags.Object && type.objectFlags & ts.ObjectFlags.Tuple) !== 0; | ||
exports.isTupleType = isTupleType; | ||
function isTupleTypeReference(type) { | ||
return _3_2_1.isTypeReference(type) && isTupleType(type.target); | ||
} | ||
exports.isTupleTypeReference = isTupleTypeReference; |
import * as ts from 'typescript'; | ||
import { PropertyName } from './util'; | ||
export declare function isEmptyObjectType(type: ts.Type): type is ts.ObjectType; | ||
@@ -8,4 +9,11 @@ export declare function removeOptionalityFromType(checker: ts.TypeChecker, type: ts.Type): ts.Type; | ||
export declare function unionTypeParts(type: ts.Type): ts.Type[]; | ||
export declare function intersectionTypeParts(type: ts.Type): ts.Type[]; | ||
export declare function someTypePart(type: ts.Type, predicate: (t: ts.Type) => t is ts.UnionOrIntersectionType, cb: (t: ts.Type) => boolean): boolean; | ||
export declare function isThenableType(checker: ts.TypeChecker, node: ts.Node, type: ts.Type): boolean; | ||
export declare function isThenableType(checker: ts.TypeChecker, node: ts.Expression, type?: ts.Type): boolean; | ||
export declare function isFalsyType(type: ts.Type): boolean; | ||
export declare function isBooleanLiteralType(type: ts.Type, literal: boolean): boolean; | ||
export declare function getPropertyOfType(type: ts.Type, name: ts.__String): ts.Symbol | undefined; | ||
export declare function isPropertyReadonlyInType(type: ts.Type, name: ts.__String, checker: ts.TypeChecker): boolean; | ||
export declare function symbolHasReadonlyDeclaration(symbol: ts.Symbol, checker: ts.TypeChecker): boolean; | ||
export declare function getPropertyNameFromType(type: ts.Type): PropertyName | undefined; |
@@ -6,2 +6,3 @@ "use strict"; | ||
const util_1 = require("./util"); | ||
const node_1 = require("../typeguard/node"); | ||
function isEmptyObjectType(type) { | ||
@@ -95,2 +96,10 @@ if (type_1.isObjectType(type) && | ||
exports.unionTypeParts = unionTypeParts; | ||
function intersectionTypeParts(type) { | ||
return type_1.isIntersectionType(type) ? type.types : [type]; | ||
} | ||
exports.intersectionTypeParts = intersectionTypeParts; | ||
function someTypePart(type, predicate, cb) { | ||
return predicate(type) ? type.types.some(cb) : cb(type); | ||
} | ||
exports.someTypePart = someTypePart; | ||
function isThenableType(checker, node, type = checker.getTypeAtLocation(node)) { | ||
@@ -127,6 +136,86 @@ for (const ty of unionTypeParts(checker.getApparentType(type))) { | ||
return !type.value; | ||
if (type.flags & ts.TypeFlags.BooleanLiteral) | ||
return type.intrinsicName === 'false'; | ||
return isBooleanLiteralType(type, false); | ||
} | ||
exports.isFalsyType = isFalsyType; | ||
function isBooleanLiteralType(type, literal) { | ||
return util_1.isTypeFlagSet(type, ts.TypeFlags.BooleanLiteral) && | ||
type.intrinsicName === (literal ? 'true' : 'false'); | ||
} | ||
exports.isBooleanLiteralType = isBooleanLiteralType; | ||
function getPropertyOfType(type, name) { | ||
return type.getProperties().find((s) => s.escapedName === name); | ||
} | ||
exports.getPropertyOfType = getPropertyOfType; | ||
function isPropertyReadonlyInType(type, name, checker) { | ||
let seenProperty = false; | ||
let seenReadonlySignature = false; | ||
for (const t of unionTypeParts(type)) { | ||
if (getPropertyOfType(t, name) === undefined) { | ||
const index = (util_1.isNumericPropertyName(name) ? checker.getIndexInfoOfType(t, ts.IndexKind.Number) : undefined) || | ||
checker.getIndexInfoOfType(t, ts.IndexKind.String); | ||
if (index !== undefined && index.isReadonly) { | ||
if (seenProperty) | ||
return true; | ||
seenReadonlySignature = true; | ||
} | ||
} | ||
else if (seenReadonlySignature || isReadonlyPropertyIntersection(t, name, checker)) { | ||
return true; | ||
} | ||
else { | ||
seenProperty = true; | ||
} | ||
} | ||
return false; | ||
} | ||
exports.isFalsyType = isFalsyType; | ||
exports.isPropertyReadonlyInType = isPropertyReadonlyInType; | ||
function isReadonlyPropertyIntersection(type, name, checker) { | ||
return someTypePart(type, type_1.isIntersectionType, (t) => { | ||
const prop = getPropertyOfType(t, name); | ||
if (prop === undefined) | ||
return false; | ||
if (prop.flags & ts.SymbolFlags.Transient) { | ||
if (/^(?:[1-9]\d*|0)$/.test(name) && type_1.isTupleTypeReference(t)) | ||
return t.target.readonly; | ||
switch (isReadonlyPropertyFromMappedType(t, name, checker)) { | ||
case true: | ||
return true; | ||
case false: | ||
return false; | ||
default: | ||
} | ||
} | ||
return (util_1.isSymbolFlagSet(prop, ts.SymbolFlags.ValueModule) || | ||
symbolHasReadonlyDeclaration(prop, checker)); | ||
}); | ||
} | ||
function isReadonlyPropertyFromMappedType(type, name, checker) { | ||
if (!type_1.isObjectType(type) || !util_1.isObjectFlagSet(type, ts.ObjectFlags.Mapped)) | ||
return; | ||
const declaration = type.symbol.declarations[0]; | ||
if (declaration.readonlyToken !== undefined && !/^__@[^@]+$/.test(name)) | ||
return declaration.readonlyToken.kind !== ts.SyntaxKind.MinusToken; | ||
return isPropertyReadonlyInType(type.modifiersType, name, checker); | ||
} | ||
function symbolHasReadonlyDeclaration(symbol, checker) { | ||
return (symbol.flags & ts.SymbolFlags.Accessor) === ts.SymbolFlags.GetAccessor || | ||
symbol.declarations !== undefined && | ||
symbol.declarations.some((node) => util_1.isModifierFlagSet(node, ts.ModifierFlags.Readonly) || | ||
node_1.isVariableDeclaration(node) && util_1.isNodeFlagSet(node.parent, ts.NodeFlags.Const) || | ||
node_1.isCallExpression(node) && util_1.isReadonlyAssignmentDeclaration(node, checker) || | ||
node_1.isEnumMember(node) || | ||
(node_1.isPropertyAssignment(node) || node_1.isShorthandPropertyAssignment(node)) && util_1.isInConstContext(node.parent)); | ||
} | ||
exports.symbolHasReadonlyDeclaration = symbolHasReadonlyDeclaration; | ||
function getPropertyNameFromType(type) { | ||
if (type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) { | ||
const value = String(type.value); | ||
return { displayName: value, symbolName: ts.escapeLeadingUnderscores(value) }; | ||
} | ||
if (type_1.isUniqueESSymbolType(type)) | ||
return { | ||
displayName: `[${type.symbol ? type.symbol.name : type.escapedName.replace(/^__@|@\d+$/g, '')}]`, | ||
symbolName: type.escapedName, | ||
}; | ||
} | ||
exports.getPropertyNameFromType = getPropertyNameFromType; |
@@ -82,2 +82,3 @@ import * as ts from 'typescript'; | ||
export declare function isValidJsxIdentifier(text: string): boolean; | ||
export declare function isNumericPropertyName(name: string | ts.__String): boolean; | ||
export declare function isSameLine(sourceFile: ts.SourceFile, pos1: number, pos2: number): boolean; | ||
@@ -137,1 +138,21 @@ export declare enum SideEffectOptions { | ||
export declare function isInConstContext(node: ts.Expression): boolean; | ||
export declare function isReadonlyAssignmentDeclaration(node: ts.CallExpression, checker: ts.TypeChecker): boolean; | ||
export declare function isBindableObjectDefinePropertyCall(node: ts.CallExpression): boolean; | ||
export interface WellKnownSymbolLiteral extends ts.PropertyAccessExpression { | ||
expression: ts.Identifier & { | ||
text: 'Symbol'; | ||
escapedText: 'symbol'; | ||
}; | ||
} | ||
export declare function isWellKnownSymbolLiterally(node: ts.Expression): node is WellKnownSymbolLiteral; | ||
export interface PropertyName { | ||
displayName: string; | ||
symbolName: ts.__String; | ||
} | ||
export declare function getPropertyNameOfWellKnownSymbol(node: WellKnownSymbolLiteral): PropertyName; | ||
export interface LateBoundPropertyNames { | ||
known: boolean; | ||
names: PropertyName[]; | ||
} | ||
export declare function getLateBoundPropertyNames(node: ts.Expression, checker: ts.TypeChecker): LateBoundPropertyNames; | ||
export declare function unwrapParentheses(node: ts.Expression): ts.Expression; |
@@ -6,2 +6,3 @@ "use strict"; | ||
const _3_2_1 = require("../typeguard/3.2"); | ||
const type_1 = require("./type"); | ||
function getChildOfKind(node, kind, sourceFile) { | ||
@@ -547,2 +548,6 @@ for (const child of node.getChildren(sourceFile)) | ||
exports.isValidJsxIdentifier = isValidJsxIdentifier; | ||
function isNumericPropertyName(name) { | ||
return String(+name) === name; | ||
} | ||
exports.isNumericPropertyName = isNumericPropertyName; | ||
function isSameLine(sourceFile, pos1, pos2) { | ||
@@ -1226,1 +1231,69 @@ return ts.getLineAndCharacterOfPosition(sourceFile, pos1).line === ts.getLineAndCharacterOfPosition(sourceFile, pos2).line; | ||
exports.isInConstContext = isInConstContext; | ||
function isReadonlyAssignmentDeclaration(node, checker) { | ||
if (!isBindableObjectDefinePropertyCall(node)) | ||
return false; | ||
const descriptorType = checker.getTypeAtLocation(node.arguments[2]); | ||
if (descriptorType.getProperty('value') === undefined) | ||
return descriptorType.getProperty('set') === undefined; | ||
const writableProp = descriptorType.getProperty('writable'); | ||
if (writableProp === undefined) | ||
return false; | ||
const writableType = writableProp.valueDeclaration !== undefined && node_1.isPropertyAssignment(writableProp.valueDeclaration) | ||
? checker.getTypeAtLocation(writableProp.valueDeclaration.initializer) | ||
: checker.getTypeOfSymbolAtLocation(writableProp, node.arguments[2]); | ||
return type_1.isBooleanLiteralType(writableType, false); | ||
} | ||
exports.isReadonlyAssignmentDeclaration = isReadonlyAssignmentDeclaration; | ||
function isBindableObjectDefinePropertyCall(node) { | ||
return node.arguments.length === 3 && | ||
node_1.isEntityNameExpression(node.arguments[0]) && | ||
node_1.isNumericOrStringLikeLiteral(node.arguments[1]) && | ||
node_1.isPropertyAccessExpression(node.expression) && | ||
node.expression.name.escapedText === 'defineProperty' && | ||
node_1.isIdentifier(node.expression.expression) && | ||
node.expression.expression.escapedText === 'Object'; | ||
} | ||
exports.isBindableObjectDefinePropertyCall = isBindableObjectDefinePropertyCall; | ||
function isWellKnownSymbolLiterally(node) { | ||
return ts.isPropertyAccessExpression(node) && | ||
ts.isIdentifier(node.expression) && | ||
node.expression.escapedText === 'Symbol'; | ||
} | ||
exports.isWellKnownSymbolLiterally = isWellKnownSymbolLiterally; | ||
function getPropertyNameOfWellKnownSymbol(node) { | ||
return { | ||
displayName: `[Symbol.${node.name.text}]`, | ||
symbolName: ('__@' + node.name.text), | ||
}; | ||
} | ||
exports.getPropertyNameOfWellKnownSymbol = getPropertyNameOfWellKnownSymbol; | ||
function getLateBoundPropertyNames(node, checker) { | ||
const result = { | ||
known: true, | ||
names: [], | ||
}; | ||
node = unwrapParentheses(node); | ||
if (isWellKnownSymbolLiterally(node)) { | ||
result.names.push(getPropertyNameOfWellKnownSymbol(node)); | ||
} | ||
else { | ||
const type = checker.getTypeAtLocation(node); | ||
for (const key of type_1.unionTypeParts(checker.getBaseConstraintOfType(type) || type)) { | ||
const propertyName = type_1.getPropertyNameFromType(key); | ||
if (propertyName) { | ||
result.names.push(propertyName); | ||
} | ||
else { | ||
result.known = false; | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
exports.getLateBoundPropertyNames = getLateBoundPropertyNames; | ||
function unwrapParentheses(node) { | ||
while (node.kind === ts.SyntaxKind.ParenthesizedExpression) | ||
node = node.expression; | ||
return node; | ||
} | ||
exports.unwrapParentheses = unwrapParentheses; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3724
184110
57