β¬ οΈ Back to Table of Contents
π no-unsafe-type-assertion¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 4 |
| π¦ Imports | 6 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/no-unsafe-type-assertion.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'no-unsafe-type-assertion' |
meta.type |
'problem' |
meta.docs.description |
'Disallow type assertions that narrow a type' |
meta.docs.requiresTypeChecking |
true |
meta.messages.unsafeOfAnyTypeAssertion |
'Unsafe assertion from {{type}} detected: consider using type guards or a safer assertion.' |
meta.messages.unsafeToAnyTypeAssertion |
'Unsafe assertion to {{type}} detected: consider using a more specific type to ensure safety.' |
meta.messages.unsafeToUnconstrainedTypeAssertion |
"Unsafe type assertion: '{{type}}' could be instantiated with an arbitrary type which could be unrelated to the origi... |
meta.messages.unsafeTypeAssertion |
"Unsafe type assertion: type '{{type}}' is more narrow than the original type." |
meta.messages.unsafeTypeAssertionAssignableToConstraint |
"Unsafe type assertion: the original type is assignable to the constraint of type '{{type}}', but '{{type}}' could be... |
meta.schema |
[] |
defaultOptions |
[] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
createRule |
../util |
getParserServices |
../util |
isTypeAnyType |
../util |
isTypeUnknownType |
../util |
isUnsafeAssignment |
../util |
Functions¶
create(context: any): { 'TSAsExpression, TSTypeAssertion'(node: TSESTree.TSAsExpr⦶
Parameters:
contextany
Returns: { 'TSAsExpression, TSTypeAssertion'(node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion): void; }
Calls:
getParserServices (from ../util)services.program.getTypeCheckertsutils.isIntrinsicErrorTypetsutils.isObjectTypetsutils.isObjectFlagSetservices.getTypeAtLocationisTypeAnyType (from ../util)isTypeUnknownType (from ../util)context.reportisUnsafeAssignment (from ../util)getAnyTypeNameisObjectLiteralTypechecker.getWidenedTypechecker.isTypeAssignableTotsutils.isTypeParameterchecker.getBaseConstraintOfTypechecker.typeToStringcheckExpression
Internal Comments:
// handle cases when asserting unknown ==> any.
// Use the widened type in case of an object literal so `isTypeAssignableTo()` (x2)
// won't fail on excess property check. (x2)
// workaround for https://github.com/microsoft/TypeScript/issues/62933
// Produce a more specific error message when targeting a type parameter
// asserting to an unconstrained type parameter is unsafe (x4)
// special case message if the original type is assignable to the (x2)
// constraint of the target type parameter (x2)
// General error message (x4)
Code
create(context) {
const services = getParserServices(context);
const checker = services.program.getTypeChecker();
function getAnyTypeName(type: ts.Type): string {
return tsutils.isIntrinsicErrorType(type) ? 'error typed' : '`any`';
}
function isObjectLiteralType(type: ts.Type): boolean {
return (
tsutils.isObjectType(type) &&
tsutils.isObjectFlagSet(type, ts.ObjectFlags.ObjectLiteral)
);
}
function checkExpression(
node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion,
): void {
const expressionType = services.getTypeAtLocation(node.expression);
const assertedType = services.getTypeAtLocation(node.typeAnnotation);
if (expressionType === assertedType) {
return;
}
// handle cases when asserting unknown ==> any.
if (isTypeAnyType(assertedType) && isTypeUnknownType(expressionType)) {
context.report({
node,
messageId: 'unsafeToAnyTypeAssertion',
data: {
type: '`any`',
},
});
return;
}
const unsafeExpressionAny = isUnsafeAssignment(
expressionType,
assertedType,
checker,
node.expression,
);
if (unsafeExpressionAny) {
context.report({
node,
messageId: 'unsafeOfAnyTypeAssertion',
data: {
type: getAnyTypeName(unsafeExpressionAny.sender),
},
});
return;
}
const unsafeAssertedAny = isUnsafeAssignment(
assertedType,
expressionType,
checker,
node.typeAnnotation,
);
if (unsafeAssertedAny) {
context.report({
node,
messageId: 'unsafeToAnyTypeAssertion',
data: {
type: getAnyTypeName(unsafeAssertedAny.sender),
},
});
return;
}
// Use the widened type in case of an object literal so `isTypeAssignableTo()`
// won't fail on excess property check.
const expressionWidenedType = isObjectLiteralType(expressionType)
? checker.getWidenedType(expressionType)
: expressionType;
let isAssertionSafe: boolean;
try {
isAssertionSafe = checker.isTypeAssignableTo(
expressionWidenedType,
assertedType,
);
} catch {
// workaround for https://github.com/microsoft/TypeScript/issues/62933
return;
}
if (isAssertionSafe) {
return;
}
// Produce a more specific error message when targeting a type parameter
if (tsutils.isTypeParameter(assertedType)) {
const assertedTypeConstraint =
checker.getBaseConstraintOfType(assertedType);
if (!assertedTypeConstraint) {
// asserting to an unconstrained type parameter is unsafe
context.report({
node,
messageId: 'unsafeToUnconstrainedTypeAssertion',
data: {
type: checker.typeToString(assertedType),
},
});
return;
}
// special case message if the original type is assignable to the
// constraint of the target type parameter
const isAssignableToConstraint = checker.isTypeAssignableTo(
expressionWidenedType,
assertedTypeConstraint,
);
if (isAssignableToConstraint) {
context.report({
node,
messageId: 'unsafeTypeAssertionAssignableToConstraint',
data: {
type: checker.typeToString(assertedType),
},
});
return;
}
}
// General error message
context.report({
node,
messageId: 'unsafeTypeAssertion',
data: {
type: checker.typeToString(assertedType),
},
});
}
return {
'TSAsExpression, TSTypeAssertion'(
node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion,
): void {
checkExpression(node);
},
};
}
Internal helpers¶
Declared inside another function in this file.
getAnyTypeName(type: ts.Type): string¶
Parameters:
typets.Type
Returns: string
Calls:
tsutils.isIntrinsicErrorType
Code
isObjectLiteralType(type: ts.Type): boolean¶
Parameters:
typets.Type
Returns: boolean
Calls:
tsutils.isObjectTypetsutils.isObjectFlagSet
Code
checkExpression(node: TSESTree.TSAsExpression | TSESTree.TSTyβ¦): void¶
Parameters:
nodeTSESTree.TSAsExpression | TSESTree.TSTypeAssertion
Returns: void
Calls:
services.getTypeAtLocationisTypeAnyType (from ../util)isTypeUnknownType (from ../util)context.reportisUnsafeAssignment (from ../util)getAnyTypeNameisObjectLiteralTypechecker.getWidenedTypechecker.isTypeAssignableTotsutils.isTypeParameterchecker.getBaseConstraintOfTypechecker.typeToString
Internal Comments:
// handle cases when asserting unknown ==> any.
// Use the widened type in case of an object literal so `isTypeAssignableTo()` (x2)
// won't fail on excess property check. (x2)
// workaround for https://github.com/microsoft/TypeScript/issues/62933
// Produce a more specific error message when targeting a type parameter
// asserting to an unconstrained type parameter is unsafe (x4)
// special case message if the original type is assignable to the (x2)
// constraint of the target type parameter (x2)
// General error message (x4)
Code
function checkExpression(
node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion,
): void {
const expressionType = services.getTypeAtLocation(node.expression);
const assertedType = services.getTypeAtLocation(node.typeAnnotation);
if (expressionType === assertedType) {
return;
}
// handle cases when asserting unknown ==> any.
if (isTypeAnyType(assertedType) && isTypeUnknownType(expressionType)) {
context.report({
node,
messageId: 'unsafeToAnyTypeAssertion',
data: {
type: '`any`',
},
});
return;
}
const unsafeExpressionAny = isUnsafeAssignment(
expressionType,
assertedType,
checker,
node.expression,
);
if (unsafeExpressionAny) {
context.report({
node,
messageId: 'unsafeOfAnyTypeAssertion',
data: {
type: getAnyTypeName(unsafeExpressionAny.sender),
},
});
return;
}
const unsafeAssertedAny = isUnsafeAssignment(
assertedType,
expressionType,
checker,
node.typeAnnotation,
);
if (unsafeAssertedAny) {
context.report({
node,
messageId: 'unsafeToAnyTypeAssertion',
data: {
type: getAnyTypeName(unsafeAssertedAny.sender),
},
});
return;
}
// Use the widened type in case of an object literal so `isTypeAssignableTo()`
// won't fail on excess property check.
const expressionWidenedType = isObjectLiteralType(expressionType)
? checker.getWidenedType(expressionType)
: expressionType;
let isAssertionSafe: boolean;
try {
isAssertionSafe = checker.isTypeAssignableTo(
expressionWidenedType,
assertedType,
);
} catch {
// workaround for https://github.com/microsoft/TypeScript/issues/62933
return;
}
if (isAssertionSafe) {
return;
}
// Produce a more specific error message when targeting a type parameter
if (tsutils.isTypeParameter(assertedType)) {
const assertedTypeConstraint =
checker.getBaseConstraintOfType(assertedType);
if (!assertedTypeConstraint) {
// asserting to an unconstrained type parameter is unsafe
context.report({
node,
messageId: 'unsafeToUnconstrainedTypeAssertion',
data: {
type: checker.typeToString(assertedType),
},
});
return;
}
// special case message if the original type is assignable to the
// constraint of the target type parameter
const isAssignableToConstraint = checker.isTypeAssignableTo(
expressionWidenedType,
assertedTypeConstraint,
);
if (isAssignableToConstraint) {
context.report({
node,
messageId: 'unsafeTypeAssertionAssignableToConstraint',
data: {
type: checker.typeToString(assertedType),
},
});
return;
}
}
// General error message
context.report({
node,
messageId: 'unsafeTypeAssertion',
data: {
type: checker.typeToString(assertedType),
},
});
}
Generated by Syntax Scribe