β¬ οΈ Back to Table of Contents
π no-unsafe-call¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 2 |
| π¦ Imports | 7 |
| π Type Aliases | 1 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/no-unsafe-call.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'no-unsafe-call' |
meta.type |
'problem' |
meta.docs.description |
'Disallow calling a value with type any' |
meta.docs.recommended |
'recommended' |
meta.docs.requiresTypeChecking |
true |
meta.messages.errorCall |
'Unsafe call of a type that could not be resolved.' |
meta.messages.errorCallThis |
'Unsafe call of a this type that could not be resolved.' |
meta.messages.errorNew |
'Unsafe construction of a type that could not be resolved.' |
meta.messages.errorTemplateTag |
'Unsafe use of a template tag whose type could not be resolved.' |
meta.messages.unsafeCall |
'Unsafe call of {{type}} typed value.' |
meta.messages.unsafeCallThis |
[ 'Unsafe call of {{type}} typed value. this is typed as {{type}}.', 'You can try to fix this by turning on the `no... |
meta.messages.unsafeNew |
'Unsafe construction of {{type}} typed value.' |
meta.messages.unsafeTemplateTag |
'Unsafe use of {{type}} typed template tag.' |
meta.schema |
[] |
defaultOptions |
[] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
createRule |
../util |
getConstrainedTypeAtLocation |
../util |
getParserServices |
../util |
getThisExpression |
../util |
isBuiltinSymbolLike |
../util |
isTypeAnyType |
../util |
Functions¶
create(context: any): { 'CallExpression > *.callee'(node: TSESTree.CallExpression⦶
Parameters:
contextany
Returns: { 'CallExpression > *.callee'(node: TSESTree.CallExpression["callee"]): void; NewExpression(node: any): void; 'TaggedTemplateExpression > *.tag'(node: TSESTree.Node): void; }
Calls:
getParserServices (from ../util)services.program.getCompilerOptionstsutils.isStrictCompilerOptionEnabledgetConstrainedTypeAtLocation (from ../util)isTypeAnyType (from ../util)getThisExpression (from ../util)tsutils.isIntrinsicErrorTypecontext.reportisBuiltinSymbolLike (from ../util)type.getConstructSignaturestype.getCallSignaturescallSignatures.sometsutils.isIntrinsicVoidTypesignature.getReturnTypecheckCall
Internal Comments:
// `this()` or `this.foo()` or `this.foo[bar]()` (x2)
// this also matches subtypes of `Function`, like `interface Foo extends Function {}`. (x2)
// (x6)
// For weird TS reasons that I don't understand, these are (x2)
// safe to construct if: (x2)
// - they have at least one call signature _that is not void-returning_, (x2)
// - OR they have at least one construct signature. (x4)
// safe to call (including as template) if: (x2)
// - they have at least one call signature (x2)
Code
create(context) {
const services = getParserServices(context);
const compilerOptions = services.program.getCompilerOptions();
const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(
compilerOptions,
'noImplicitThis',
);
function checkCall(
node: TSESTree.Node,
reportingNode: TSESTree.Node,
unsafeMessageId: Extract<MessageIds, `unsafe${string}`>,
errorMessageId: Extract<MessageIds, `error${string}`>,
): void {
const type = getConstrainedTypeAtLocation(services, node);
if (isTypeAnyType(type)) {
if (!isNoImplicitThis) {
// `this()` or `this.foo()` or `this.foo[bar]()`
const thisExpression = getThisExpression(node);
if (
thisExpression &&
isTypeAnyType(
getConstrainedTypeAtLocation(services, thisExpression),
)
) {
unsafeMessageId = 'unsafeCallThis';
errorMessageId = 'errorCallThis';
}
}
const isErrorType = tsutils.isIntrinsicErrorType(type);
context.report({
node: reportingNode,
messageId: isErrorType ? errorMessageId : unsafeMessageId,
data: {
type: 'an `any`',
},
});
return;
}
if (isBuiltinSymbolLike(services.program, type, 'Function')) {
// this also matches subtypes of `Function`, like `interface Foo extends Function {}`.
//
// For weird TS reasons that I don't understand, these are
//
// safe to construct if:
// - they have at least one call signature _that is not void-returning_,
// - OR they have at least one construct signature.
//
// safe to call (including as template) if:
// - they have at least one call signature
// - OR they have at least one construct signature.
const constructSignatures = type.getConstructSignatures();
if (constructSignatures.length > 0) {
return;
}
const callSignatures = type.getCallSignatures();
if (unsafeMessageId === 'unsafeNew') {
if (
callSignatures.some(
signature =>
!tsutils.isIntrinsicVoidType(signature.getReturnType()),
)
) {
return;
}
} else if (callSignatures.length > 0) {
return;
}
context.report({
node: reportingNode,
messageId: unsafeMessageId,
data: {
type: 'a `Function`',
},
});
return;
}
}
return {
'CallExpression > *.callee'(
node: TSESTree.CallExpression['callee'],
): void {
checkCall(node, node, 'unsafeCall', 'errorCall');
},
NewExpression(node): void {
checkCall(node.callee, node, 'unsafeNew', 'errorNew');
},
'TaggedTemplateExpression > *.tag'(node: TSESTree.Node): void {
checkCall(node, node, 'unsafeTemplateTag', 'errorTemplateTag');
},
};
}
Internal helpers¶
Declared inside another function in this file.
checkCall(node: TSESTree.Node, reportingNode: TSESTree.Node, unsafeMessageId: Extract<MessageIds,unsafe${string}>, errorMessageId: Extract<MessageIds,error${string}>): void¶
Parameters:
nodeTSESTree.NodereportingNodeTSESTree.NodeunsafeMessageIdExtract<MessageIds,unsafe${string}>errorMessageIdExtract<MessageIds,error${string}>
Returns: void
Calls:
getConstrainedTypeAtLocation (from ../util)isTypeAnyType (from ../util)getThisExpression (from ../util)tsutils.isIntrinsicErrorTypecontext.reportisBuiltinSymbolLike (from ../util)type.getConstructSignaturestype.getCallSignaturescallSignatures.sometsutils.isIntrinsicVoidTypesignature.getReturnType
Internal Comments:
// `this()` or `this.foo()` or `this.foo[bar]()` (x2)
// this also matches subtypes of `Function`, like `interface Foo extends Function {}`. (x2)
// (x6)
// For weird TS reasons that I don't understand, these are (x2)
// safe to construct if: (x2)
// - they have at least one call signature _that is not void-returning_, (x2)
// - OR they have at least one construct signature. (x4)
// safe to call (including as template) if: (x2)
// - they have at least one call signature (x2)
Code
function checkCall(
node: TSESTree.Node,
reportingNode: TSESTree.Node,
unsafeMessageId: Extract<MessageIds, `unsafe${string}`>,
errorMessageId: Extract<MessageIds, `error${string}`>,
): void {
const type = getConstrainedTypeAtLocation(services, node);
if (isTypeAnyType(type)) {
if (!isNoImplicitThis) {
// `this()` or `this.foo()` or `this.foo[bar]()`
const thisExpression = getThisExpression(node);
if (
thisExpression &&
isTypeAnyType(
getConstrainedTypeAtLocation(services, thisExpression),
)
) {
unsafeMessageId = 'unsafeCallThis';
errorMessageId = 'errorCallThis';
}
}
const isErrorType = tsutils.isIntrinsicErrorType(type);
context.report({
node: reportingNode,
messageId: isErrorType ? errorMessageId : unsafeMessageId,
data: {
type: 'an `any`',
},
});
return;
}
if (isBuiltinSymbolLike(services.program, type, 'Function')) {
// this also matches subtypes of `Function`, like `interface Foo extends Function {}`.
//
// For weird TS reasons that I don't understand, these are
//
// safe to construct if:
// - they have at least one call signature _that is not void-returning_,
// - OR they have at least one construct signature.
//
// safe to call (including as template) if:
// - they have at least one call signature
// - OR they have at least one construct signature.
const constructSignatures = type.getConstructSignatures();
if (constructSignatures.length > 0) {
return;
}
const callSignatures = type.getCallSignatures();
if (unsafeMessageId === 'unsafeNew') {
if (
callSignatures.some(
signature =>
!tsutils.isIntrinsicVoidType(signature.getReturnType()),
)
) {
return;
}
} else if (callSignatures.length > 0) {
return;
}
context.report({
node: reportingNode,
messageId: unsafeMessageId,
data: {
type: 'a `Function`',
},
});
return;
}
}
Type Aliases¶
MessageIds¶
type MessageIds = | 'errorCall'
| 'errorCallThis'
| 'errorNew'
| 'errorTemplateTag'
| 'unsafeCall'
| 'unsafeCallThis'
| 'unsafeNew'
| 'unsafeTemplateTag';
Generated by Syntax Scribe