📄 restrict-template-expressions¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 3 |
| 📦 Imports | 16 |
| 📑 Type Aliases | 3 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin/src/rules/restrict-template-expressions.ts
📤 Default Export¶
| Property | Value |
|---|---|
name |
'restrict-template-expressions' |
meta.type |
'problem' |
meta.docs.description |
'Enforce template literal expressions to be of string type' |
meta.docs.recommended.recommended |
true |
meta.docs.recommended.strict |
[ { allowAny: false, allowBoolean: false, allowNever: false, allowNullish: false, allowNumber: false, allowRegExp: fa... |
meta.docs.requiresTypeChecking |
true |
meta.messages.invalidType |
'Invalid type "{{type}}" of template literal expression.' |
meta.schema |
[ { type: 'object', additionalProperties: false, properties: { ...Object.fromEntries( optionTesters.map(({ type, opti... |
defaultOptions |
[ { allow: [{ name: ['Error', 'URL', 'URLSearchParams'], from: 'lib' }], allowAny: true, allowBoolean: true, allowNul... |
Entry point: create — documented under Functions.
📦 Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
Type |
typescript |
TypeChecker |
typescript |
typeMatchesSomeSpecifier |
@typescript-eslint/type-utils |
typeOrValueSpecifiersSchema |
@typescript-eslint/type-utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
TypeFlags |
typescript |
TypeOrValueSpecifier |
../util |
createRule |
../util |
getConstrainedTypeAtLocation |
../util |
getParserServices |
../util |
getTypeName |
../util |
isTypeAnyType |
../util |
isTypeFlagSet |
../util |
isTypeNeverType |
../util |
matchesTypeOrBaseType |
../util |
Functions¶
create(context: any, [{ allow, ...options }]: any): { TemplateLiteral(node: TSESTree.TemplateLiteral): void; }¶
Parameters:
contextany[{ allow, ...options }]any
Returns: { TemplateLiteral(node: TSESTree.TemplateLiteral): void; }
Calls:
getParserServices (from ../util)program.getTypeCheckeroptionTesters.filtergetConstrainedTypeAtLocation (from ../util)recursivelyCheckTypecontext.reportchecker.typeToStringinnerType.isUnioninnerType.types.everyinnerType.isIntersectioninnerType.types.someisTypeFlagSet (from ../util)matchesTypeOrBaseType (from ../util)typeMatchesSomeSpecifier (from @typescript-eslint/type-utils)enabledOptionTesters.sometester
Internal Comments:
Code
create(context, [{ allow, ...options }]) {
const services = getParserServices(context);
const { program } = services;
const checker = program.getTypeChecker();
const enabledOptionTesters = optionTesters.filter(
({ option }) => options[option],
);
return {
TemplateLiteral(node: TSESTree.TemplateLiteral): void {
// don't check tagged template literals
if (node.parent.type === AST_NODE_TYPES.TaggedTemplateExpression) {
return;
}
for (const expression of node.expressions) {
const expressionType = getConstrainedTypeAtLocation(
services,
expression,
);
if (!recursivelyCheckType(expressionType)) {
context.report({
node: expression,
messageId: 'invalidType',
data: { type: checker.typeToString(expressionType) },
});
}
}
},
};
function recursivelyCheckType(innerType: Type): boolean {
if (innerType.isUnion()) {
return innerType.types.every(recursivelyCheckType);
}
if (innerType.isIntersection()) {
return innerType.types.some(recursivelyCheckType);
}
return (
isTypeFlagSet(innerType, TypeFlags.StringLike) ||
matchesTypeOrBaseType(
services,
type => typeMatchesSomeSpecifier(type, allow, program),
innerType,
) ||
enabledOptionTesters.some(({ tester }) =>
tester(innerType, checker, recursivelyCheckType),
)
);
}
}
testTypeFlag(flagsToCheck: TypeFlags): OptionTester¶
Parameters:
flagsToCheckTypeFlags
Returns: OptionTester
Internal helpers¶
Declared inside another function in this file.
recursivelyCheckType(innerType: Type): boolean¶
Parameters:
innerTypeType
Returns: boolean
Calls:
innerType.isUnioninnerType.types.everyinnerType.isIntersectioninnerType.types.someisTypeFlagSet (from ../util)matchesTypeOrBaseType (from ../util)typeMatchesSomeSpecifier (from @typescript-eslint/type-utils)enabledOptionTesters.sometester
Code
function recursivelyCheckType(innerType: Type): boolean {
if (innerType.isUnion()) {
return innerType.types.every(recursivelyCheckType);
}
if (innerType.isIntersection()) {
return innerType.types.some(recursivelyCheckType);
}
return (
isTypeFlagSet(innerType, TypeFlags.StringLike) ||
matchesTypeOrBaseType(
services,
type => typeMatchesSomeSpecifier(type, allow, program),
innerType,
) ||
enabledOptionTesters.some(({ tester }) =>
tester(innerType, checker, recursivelyCheckType),
)
);
}
Type Aliases¶
OptionTester¶
type OptionTester = (
type: Type,
checker: TypeChecker,
recursivelyCheckType: (type: Type) => boolean,
) => boolean;
Options¶
type Options = [
{
allow?: TypeOrValueSpecifier[];
} & Partial<Record<(typeof optionTesters)[number]['option'], boolean>>,
];
MessageId¶
Generated by Syntax Scribe