📄 no-type-alias¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 8 |
| 📦 Imports | 4 |
| 📐 Interfaces | 1 |
| 📑 Type Aliases | 4 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin/src/rules/no-type-alias.ts
📤 Default Export¶
| Property | Value |
|---|---|
name |
'no-type-alias' |
meta.type |
'suggestion' |
meta.deprecated.deprecatedSince |
'6.0.0' |
meta.deprecated.replacedBy |
[ { rule: { name: '@typescript-eslint/consistent-type-definitions', url: 'https://typescript-eslint.io/rules/consiste... |
meta.deprecated.url |
'https://github.com/typescript-eslint/typescript-eslint/pull/6229' |
meta.docs.description |
'Disallow type aliases' |
meta.messages.noCompositionAlias |
'{{typeName}} in {{compositionType}} types are not allowed.' |
meta.messages.noTypeAlias |
'Type {{alias}} are not allowed.' |
meta.schema |
[ { type: 'object', $defs: { expandedOptions: { type: 'string', enum: [ 'always', 'never', 'in-unions', 'in-intersect... |
defaultOptions |
[ { allowAliases: 'never', allowCallbacks: 'never', allowConditionalTypes: 'never', allowConstructors: 'never', allow... |
Entry point: create — documented under Functions.
📦 Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
AST_TOKEN_TYPES |
@typescript-eslint/utils |
createRule |
../util |
Functions¶
create(context: any, [ { allowAliases, allowCallback…: any): { TSTypeAliasDeclaration(node: any): void; }¶
Parameters:
contextany[ { allowAliases, allowCallbacks, allowConditionalTypes, allowConstructors, allowGenerics, allowLiterals, allowMappedTypes, allowTupleTypes, }, ]any
Returns: { TSTypeAliasDeclaration(node: any): void; }
Calls:
compositions.includesunions.includesintersections.includescontext.reporttype.toLowerCase['keyof', 'readonly'].includesisSupportedCompositionreportErrorcheckAndReportisValidTupleTypeisValidGenerictype.node.type.endsWithaliasTypes.hasnode.types.flatMapgetTypesvalidateTypeAliasestypes.forEach
Internal Comments:
/**
* Determines if the composition type is supported by the allowed flags.
* @param isTopLevel a flag indicating this is the top level node.
* @param compositionType the composition type (either TSUnionType or TSIntersectionType)
* @param allowed the currently allowed flags.
*/
/**
* Gets the message to be displayed based on the node type and whether the node is a top level declaration.
* @param node the location
* @param compositionType the type of composition this alias is part of (undefined if not
* part of a composition)
* @param isRoot a flag indicating we are dealing with the top level declaration.
* @param type the kind of type alias being validated.
*/
/**
* Validates the node looking for aliases, callbacks and literals.
* @param type the type of composition this alias is part of (null if not
* part of a composition)
* @param isTopLevel a flag indicating this is the top level node.
*/
// https://github.com/typescript-eslint/typescript-eslint/issues/5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
// callback
// conditional type
// literal object type (x3)
// mapped type (x3)
// tuple types (x3)
// alias / keyword (x3)
// unhandled type - shouldn't happen (x3)
/**
* Flatten the given type into an array of its dependencies
*/
// is a top level type annotation (x3)
// is a composition type (x4)
Code
create(
context,
[
{
allowAliases,
allowCallbacks,
allowConditionalTypes,
allowConstructors,
allowGenerics,
allowLiterals,
allowMappedTypes,
allowTupleTypes,
},
],
) {
const unions = ['always', 'in-unions', 'in-unions-and-intersections'];
const intersections = [
'always',
'in-intersections',
'in-unions-and-intersections',
];
const compositions = [
'in-unions',
'in-intersections',
'in-unions-and-intersections',
];
const aliasTypes = new Set([
AST_NODE_TYPES.TSArrayType,
AST_NODE_TYPES.TSImportType,
AST_NODE_TYPES.TSIndexedAccessType,
AST_NODE_TYPES.TSLiteralType,
AST_NODE_TYPES.TSTemplateLiteralType,
AST_NODE_TYPES.TSTypeQuery,
AST_NODE_TYPES.TSTypeReference,
]);
/**
* Determines if the composition type is supported by the allowed flags.
* @param isTopLevel a flag indicating this is the top level node.
* @param compositionType the composition type (either TSUnionType or TSIntersectionType)
* @param allowed the currently allowed flags.
*/
function isSupportedComposition(
isTopLevel: boolean,
compositionType: CompositionType | null,
allowed: string,
): boolean {
return (
!compositions.includes(allowed) ||
(!isTopLevel &&
((compositionType === AST_NODE_TYPES.TSUnionType &&
unions.includes(allowed)) ||
(compositionType === AST_NODE_TYPES.TSIntersectionType &&
intersections.includes(allowed))))
);
}
/**
* Gets the message to be displayed based on the node type and whether the node is a top level declaration.
* @param node the location
* @param compositionType the type of composition this alias is part of (undefined if not
* part of a composition)
* @param isRoot a flag indicating we are dealing with the top level declaration.
* @param type the kind of type alias being validated.
*/
function reportError(
node: TSESTree.Node,
compositionType: CompositionType | null,
isRoot: boolean,
type: string,
): void {
if (isRoot) {
return context.report({
node,
messageId: 'noTypeAlias',
data: {
alias: type.toLowerCase(),
},
});
}
return context.report({
node,
messageId: 'noCompositionAlias',
data: {
compositionType:
compositionType === AST_NODE_TYPES.TSUnionType
? 'union'
: 'intersection',
typeName: type,
},
});
}
const isValidTupleType = (type: TypeWithLabel): boolean => {
if (type.node.type === AST_NODE_TYPES.TSTupleType) {
return true;
}
if (
type.node.type === AST_NODE_TYPES.TSTypeOperator &&
['keyof', 'readonly'].includes(type.node.operator) &&
type.node.typeAnnotation?.type === AST_NODE_TYPES.TSTupleType
) {
return true;
}
return false;
};
const isValidGeneric = (type: TypeWithLabel): boolean => {
return (
type.node.type === AST_NODE_TYPES.TSTypeReference &&
type.node.typeArguments != null
);
};
const checkAndReport = (
optionValue: Values,
isTopLevel: boolean,
type: TypeWithLabel,
label: string,
): void => {
if (
optionValue === 'never' ||
!isSupportedComposition(isTopLevel, type.compositionType, optionValue)
) {
reportError(type.node, type.compositionType, isTopLevel, label);
}
};
/**
* Validates the node looking for aliases, callbacks and literals.
* @param type the type of composition this alias is part of (null if not
* part of a composition)
* @param isTopLevel a flag indicating this is the top level node.
*/
function validateTypeAliases(
type: TypeWithLabel,
isTopLevel = false,
): void {
// https://github.com/typescript-eslint/typescript-eslint/issues/5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
if (type.node.type === AST_NODE_TYPES.TSFunctionType) {
// callback
if (allowCallbacks === 'never') {
reportError(type.node, type.compositionType, isTopLevel, 'Callbacks');
}
} else if (type.node.type === AST_NODE_TYPES.TSConditionalType) {
// conditional type
if (allowConditionalTypes === 'never') {
reportError(
type.node,
type.compositionType,
isTopLevel,
'Conditional types',
);
}
} else if (type.node.type === AST_NODE_TYPES.TSConstructorType) {
if (allowConstructors === 'never') {
reportError(
type.node,
type.compositionType,
isTopLevel,
'Constructors',
);
}
} else if (type.node.type === AST_NODE_TYPES.TSTypeLiteral) {
// literal object type
checkAndReport(allowLiterals!, isTopLevel, type, 'Literals');
} else if (type.node.type === AST_NODE_TYPES.TSMappedType) {
// mapped type
checkAndReport(allowMappedTypes!, isTopLevel, type, 'Mapped types');
} else if (isValidTupleType(type)) {
// tuple types
checkAndReport(allowTupleTypes!, isTopLevel, type, 'Tuple Types');
} else if (isValidGeneric(type)) {
if (allowGenerics === 'never') {
reportError(type.node, type.compositionType, isTopLevel, 'Generics');
}
} else if (
type.node.type.endsWith(AST_TOKEN_TYPES.Keyword) ||
aliasTypes.has(type.node.type) ||
(type.node.type === AST_NODE_TYPES.TSTypeOperator &&
(type.node.operator === 'keyof' ||
(type.node.operator === 'readonly' &&
type.node.typeAnnotation &&
aliasTypes.has(type.node.typeAnnotation.type))))
) {
// alias / keyword
checkAndReport(allowAliases!, isTopLevel, type, 'Aliases');
} else {
// unhandled type - shouldn't happen
reportError(type.node, type.compositionType, isTopLevel, 'Unhandled');
}
/* eslint-enable @typescript-eslint/no-non-null-assertion */
}
/**
* Flatten the given type into an array of its dependencies
*/
function getTypes(
node: TSESTree.Node,
compositionType: CompositionType | null = null,
): TypeWithLabel[] {
if (
node.type === AST_NODE_TYPES.TSUnionType ||
node.type === AST_NODE_TYPES.TSIntersectionType
) {
return node.types.flatMap(type => getTypes(type, node.type));
}
return [{ node, compositionType }];
}
return {
TSTypeAliasDeclaration(node): void {
const types = getTypes(node.typeAnnotation);
if (types.length === 1) {
// is a top level type annotation
validateTypeAliases(types[0], true);
} else {
// is a composition type
types.forEach(type => {
validateTypeAliases(type);
});
}
},
};
}
Internal helpers¶
Declared inside another function in this file.
isSupportedComposition(isTopLevel: boolean, compositionType: CompositionType | null, allowed: string): boolean¶
Determines if the composition type is supported by the allowed flags.
Parameters:
isTopLevelany: a flag indicating this is the top level node.compositionTypeany: the composition type (either TSUnionType or TSIntersectionType)allowedany: the currently allowed flags.
Raw JSDoc
Calls:
compositions.includesunions.includesintersections.includes
Code
function isSupportedComposition(
isTopLevel: boolean,
compositionType: CompositionType | null,
allowed: string,
): boolean {
return (
!compositions.includes(allowed) ||
(!isTopLevel &&
((compositionType === AST_NODE_TYPES.TSUnionType &&
unions.includes(allowed)) ||
(compositionType === AST_NODE_TYPES.TSIntersectionType &&
intersections.includes(allowed))))
);
}
reportError(node: TSESTree.Node, compositionType: CompositionType | null, isRoot: boolean, type: string): void¶
Gets the message to be displayed based on the node type and whether the node is a top level declaration.
Parameters:
nodeany: the locationcompositionTypeany: the type of composition this alias is part of (undefined if not part of a composition)isRootany: a flag indicating we are dealing with the top level declaration.typeany: the kind of type alias being validated.
Raw JSDoc
/**
* Gets the message to be displayed based on the node type and whether the node is a top level declaration.
* @param node the location
* @param compositionType the type of composition this alias is part of (undefined if not
* part of a composition)
* @param isRoot a flag indicating we are dealing with the top level declaration.
* @param type the kind of type alias being validated.
*/
Calls:
context.reporttype.toLowerCase
Code
function reportError(
node: TSESTree.Node,
compositionType: CompositionType | null,
isRoot: boolean,
type: string,
): void {
if (isRoot) {
return context.report({
node,
messageId: 'noTypeAlias',
data: {
alias: type.toLowerCase(),
},
});
}
return context.report({
node,
messageId: 'noCompositionAlias',
data: {
compositionType:
compositionType === AST_NODE_TYPES.TSUnionType
? 'union'
: 'intersection',
typeName: type,
},
});
}
isValidTupleType(type: TypeWithLabel): boolean¶
Parameters:
typeTypeWithLabel
Returns: boolean
Calls:
['keyof', 'readonly'].includes
Code
(type: TypeWithLabel): boolean => {
if (type.node.type === AST_NODE_TYPES.TSTupleType) {
return true;
}
if (
type.node.type === AST_NODE_TYPES.TSTypeOperator &&
['keyof', 'readonly'].includes(type.node.operator) &&
type.node.typeAnnotation?.type === AST_NODE_TYPES.TSTupleType
) {
return true;
}
return false;
}
isValidGeneric(type: TypeWithLabel): boolean¶
Parameters:
typeTypeWithLabel
Returns: boolean
Code
checkAndReport(optionValue: Values, isTopLevel: boolean, type: TypeWithLabel, label: string): void¶
Parameters:
optionValueValuesisTopLevelbooleantypeTypeWithLabellabelstring
Returns: void
Calls:
isSupportedCompositionreportError
Code
validateTypeAliases(type: TypeWithLabel, isTopLevel: boolean): void¶
Validates the node looking for aliases, callbacks and literals.
Parameters:
typeany: the type of composition this alias is part of (null if not part of a composition)isTopLevelany: a flag indicating this is the top level node.
Raw JSDoc
Calls:
reportErrorcheckAndReportisValidTupleTypeisValidGenerictype.node.type.endsWithaliasTypes.has
Internal Comments:
// https://github.com/typescript-eslint/typescript-eslint/issues/5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
// callback
// conditional type
// literal object type (x3)
// mapped type (x3)
// tuple types (x3)
// alias / keyword (x3)
// unhandled type - shouldn't happen (x3)
Code
function validateTypeAliases(
type: TypeWithLabel,
isTopLevel = false,
): void {
// https://github.com/typescript-eslint/typescript-eslint/issues/5439
/* eslint-disable @typescript-eslint/no-non-null-assertion */
if (type.node.type === AST_NODE_TYPES.TSFunctionType) {
// callback
if (allowCallbacks === 'never') {
reportError(type.node, type.compositionType, isTopLevel, 'Callbacks');
}
} else if (type.node.type === AST_NODE_TYPES.TSConditionalType) {
// conditional type
if (allowConditionalTypes === 'never') {
reportError(
type.node,
type.compositionType,
isTopLevel,
'Conditional types',
);
}
} else if (type.node.type === AST_NODE_TYPES.TSConstructorType) {
if (allowConstructors === 'never') {
reportError(
type.node,
type.compositionType,
isTopLevel,
'Constructors',
);
}
} else if (type.node.type === AST_NODE_TYPES.TSTypeLiteral) {
// literal object type
checkAndReport(allowLiterals!, isTopLevel, type, 'Literals');
} else if (type.node.type === AST_NODE_TYPES.TSMappedType) {
// mapped type
checkAndReport(allowMappedTypes!, isTopLevel, type, 'Mapped types');
} else if (isValidTupleType(type)) {
// tuple types
checkAndReport(allowTupleTypes!, isTopLevel, type, 'Tuple Types');
} else if (isValidGeneric(type)) {
if (allowGenerics === 'never') {
reportError(type.node, type.compositionType, isTopLevel, 'Generics');
}
} else if (
type.node.type.endsWith(AST_TOKEN_TYPES.Keyword) ||
aliasTypes.has(type.node.type) ||
(type.node.type === AST_NODE_TYPES.TSTypeOperator &&
(type.node.operator === 'keyof' ||
(type.node.operator === 'readonly' &&
type.node.typeAnnotation &&
aliasTypes.has(type.node.typeAnnotation.type))))
) {
// alias / keyword
checkAndReport(allowAliases!, isTopLevel, type, 'Aliases');
} else {
// unhandled type - shouldn't happen
reportError(type.node, type.compositionType, isTopLevel, 'Unhandled');
}
/* eslint-enable @typescript-eslint/no-non-null-assertion */
}
getTypes(node: TSESTree.Node, compositionType: CompositionType | null): TypeWithLabel[]¶
Flatten the given type into an array of its dependencies
Calls:
node.types.flatMapgetTypes
Code
function getTypes(
node: TSESTree.Node,
compositionType: CompositionType | null = null,
): TypeWithLabel[] {
if (
node.type === AST_NODE_TYPES.TSUnionType ||
node.type === AST_NODE_TYPES.TSIntersectionType
) {
return node.types.flatMap(type => getTypes(type, node.type));
}
return [{ node, compositionType }];
}
Interfaces¶
TypeWithLabel¶
Interface Code
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
compositionType |
CompositionType \| null |
✗ | not shown |
node |
TSESTree.Node |
✗ | not shown |
Type Aliases¶
Values¶
type Values = | 'always'
| 'in-intersections'
| 'in-unions'
| 'in-unions-and-intersections'
| 'never';
Options¶
type Options = [
{
allowAliases?: Values;
allowCallbacks?: 'always' | 'never';
allowConditionalTypes?: 'always' | 'never';
allowConstructors?: 'always' | 'never';
allowGenerics?: 'always' | 'never';
allowLiterals?: Values;
allowMappedTypes?: Values;
allowTupleTypes?: Values;
},
];
MessageIds¶
CompositionType¶
Generated by Syntax Scribe