📄 no-redundant-type-constituents.ts¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 10 |
| 📦 Imports | 11 |
| 📊 Variables & Constants | 14 |
| 📐 Interfaces | 3 |
| 📑 Type Aliases | 1 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts
📦 Imports¶
| Name | Source |
|---|---|
AST_NODE_TYPES |
@typescript-eslint/utils |
TSESTree |
@typescript-eslint/utils |
arrayGroupByToMap |
../util |
createRule |
../util |
getParserServices |
../util |
isFunctionOrFunctionType |
../util |
isTypeAnyType |
../util |
isTypeBigIntLiteralType |
../util |
isTypeNeverType |
../util |
isTypeTemplateLiteralType |
../util |
isTypeUnknownType |
../util |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
literalToPrimitiveTypeFlags |
{ readonly [x: number]: any; } |
const | `{ | |
| [ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt, | ||||
| [ts.TypeFlags.BooleanLiteral]: ts.TypeFlags.Boolean, | ||||
| [ts.TypeFlags.NumberLiteral]: ts.TypeFlags.Number, | ||||
| [ts.TypeFlags.StringLiteral]: ts.TypeFlags.String, | ||||
| [ts.TypeFlags.TemplateLiteral]: ts.TypeFlags.String, | ||||
| } as const` | ✗ | |||
literalTypeFlags |
readonly [any, any, any, any, any] |
const | `[ | |
| ts.TypeFlags.BigIntLiteral, | ||||
| ts.TypeFlags.BooleanLiteral, | ||||
| ts.TypeFlags.NumberLiteral, | ||||
| ts.TypeFlags.StringLiteral, | ||||
| ts.TypeFlags.TemplateLiteral, | ||||
| ] as const` | ✗ | |||
primitiveTypeFlags |
readonly [any, any, any, any] |
const | `[ | |
| ts.TypeFlags.BigInt, | ||||
| ts.TypeFlags.Boolean, | ||||
| ts.TypeFlags.Number, | ||||
| ts.TypeFlags.String, | ||||
| ] as const` | ✗ | |||
primitiveTypeFlagNames |
{ readonly [x: number]: "string" | "number" | "bigint" | "boolean"; } |
const | `{ | |
| [ts.TypeFlags.BigInt]: 'bigint', | ||||
| [ts.TypeFlags.Boolean]: 'boolean', | ||||
| [ts.TypeFlags.Number]: 'number', | ||||
| [ts.TypeFlags.String]: 'string', | ||||
| } as const` | ✗ | |||
primitiveTypeFlagTypes |
{ readonly bigint: any; readonly boolean: any; readonly number: any; readonly string: any; } |
const | `{ | |
| bigint: ts.TypeFlags.BigIntLiteral, | ||||
| boolean: ts.TypeFlags.BooleanLiteral, | ||||
| number: ts.TypeFlags.NumberLiteral, | ||||
| string: ts.TypeFlags.StringLiteral, | ||||
| } as const` | ✗ | |||
keywordNodeTypesToTsTypes |
Map<any, any> |
const | `new Map([ | |
| [TSESTree.AST_NODE_TYPES.TSAnyKeyword, ts.TypeFlags.Any], | ||||
| [TSESTree.AST_NODE_TYPES.TSBigIntKeyword, ts.TypeFlags.BigInt], | ||||
| [TSESTree.AST_NODE_TYPES.TSBooleanKeyword, ts.TypeFlags.Boolean], | ||||
| [TSESTree.AST_NODE_TYPES.TSNeverKeyword, ts.TypeFlags.Never], | ||||
| [TSESTree.AST_NODE_TYPES.TSNumberKeyword, ts.TypeFlags.Number], | ||||
| [TSESTree.AST_NODE_TYPES.TSStringKeyword, ts.TypeFlags.String], | ||||
| [TSESTree.AST_NODE_TYPES.TSUnknownKeyword, ts.TypeFlags.Unknown], | ||||
| ])` | ✗ | |||
typesCache |
Map<TSESTree.TypeNode, TypeFlagsWithName[]> |
const | new Map<TSESTree.TypeNode, TypeFlagsWithName[]>() |
✗ |
seenLiteralTypes |
Map<any, string[]> |
const | new Map<PrimitiveTypeFlag, string[]>() |
✗ |
seenPrimitiveTypes |
Map<any, TSESTree.TypeNode[]> |
const | `new Map< | |
| PrimitiveTypeFlag, | ||||
| TSESTree.TypeNode[] | ||||
| >()` | ✗ | |||
seenUnionTypes |
Map<TSESTree.TypeNode, TypeFlagsWithName[]> |
const | `new Map< | |
| TSESTree.TypeNode, | ||||
| TypeFlagsWithName[] | ||||
| >()` | ✗ | |||
primitive |
number | undefined |
let/var | undefined |
✗ |
seenLiteralTypes |
Map<any, TypeNodeWithValue[]> |
const | `new Map< | |
| PrimitiveTypeFlag, | ||||
| TypeNodeWithValue[] | ||||
| >()` | ✗ | |||
seenPrimitiveTypes |
Set<any> |
const | new Set<PrimitiveTypeFlag>() |
✗ |
overriddenTypeNodes |
Map<TSESTree.TypeNode, TypeFlagWithText[]> |
const | `new Map< | |
| TSESTree.TypeNode, | ||||
| TypeFlagWithText[] | ||||
| >()` | ✗ |
Functions¶
addToMapGroup(map: Map<Key, Value[]>, key: Key, value: Value): void¶
Code
- Parameters:
map: Map<Key, Value[]>key: Keyvalue: Value- Return Type:
void - Calls:
map.getexisting.pushmap.set
describeLiteralType(type: ts.Type): string¶
Code
function describeLiteralType(type: ts.Type): string {
if (type.isStringLiteral()) {
return JSON.stringify(type.value);
}
if (isTypeBigIntLiteralType(type)) {
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
}
if (type.isLiteral()) {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
return type.value.toString();
}
if (tsutils.isIntrinsicErrorType(type) && type.aliasSymbol) {
return type.aliasSymbol.escapedName.toString();
}
if (isTypeAnyType(type)) {
return 'any';
}
if (isTypeNeverType(type)) {
return 'never';
}
if (isTypeUnknownType(type)) {
return 'unknown';
}
if (isTypeTemplateLiteralType(type)) {
return 'template literal type';
}
if (isTypeBigIntLiteralType(type)) {
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`;
}
if (tsutils.isTrueLiteralType(type)) {
return 'true';
}
if (tsutils.isFalseLiteralType(type)) {
return 'false';
}
return 'literal type';
}
- Parameters:
type: ts.Type- Return Type:
string - Calls:
type.isStringLiteralJSON.stringifyisTypeBigIntLiteralType (from ../util)type.isLiteraltype.value.toStringtsutils.isIntrinsicErrorTypetype.aliasSymbol.escapedName.toStringisTypeAnyType (from ../util)isTypeNeverType (from ../util)isTypeUnknownType (from ../util)isTypeTemplateLiteralType (from ../util)tsutils.isTrueLiteralTypetsutils.isFalseLiteralType- Internal Comments:
describeLiteralTypeNode(typeNode: TSESTree.TypeNode): string¶
Code
function describeLiteralTypeNode(typeNode: TSESTree.TypeNode): string {
switch (typeNode.type) {
case AST_NODE_TYPES.TSAnyKeyword:
return 'any';
case AST_NODE_TYPES.TSBooleanKeyword:
return 'boolean';
case AST_NODE_TYPES.TSNeverKeyword:
return 'never';
case AST_NODE_TYPES.TSNumberKeyword:
return 'number';
case AST_NODE_TYPES.TSStringKeyword:
return 'string';
case AST_NODE_TYPES.TSUnknownKeyword:
return 'unknown';
case AST_NODE_TYPES.TSLiteralType:
switch (typeNode.literal.type) {
case TSESTree.AST_NODE_TYPES.Literal:
switch (typeof typeNode.literal.value) {
case 'bigint':
return `${typeNode.literal.value < 0 ? '-' : ''}${
typeNode.literal.value
}n`;
case 'string':
return JSON.stringify(typeNode.literal.value);
default:
return `${typeNode.literal.value}`;
}
case TSESTree.AST_NODE_TYPES.TemplateLiteral:
return 'template literal type';
}
}
return 'literal type';
}
- Parameters:
typeNode: TSESTree.TypeNode- Return Type:
string - Calls:
JSON.stringify
isNodeInsideReturnType(node: TSESTree.TSUnionType): boolean¶
Code
- Parameters:
node: TSESTree.TSUnionType- Return Type:
boolean - Calls:
isFunctionOrFunctionType (from ../util)
unionTypePartsUnlessBoolean(type: ts.Type): ts.Type[]¶
Code
-
JSDoc:
-
Parameters:
type: ts.Type- Return Type:
ts.Type[] - Calls:
type.isUniontsutils.isFalseLiteralTypetsutils.isTrueLiteralTypetsutils.unionConstituents
getTypeNodeTypePartFlags(typeNode: TSESTree.TypeNode): TypeFlagsWithName[]¶
Code
function getTypeNodeTypePartFlags(
typeNode: TSESTree.TypeNode,
): TypeFlagsWithName[] {
const keywordTypeFlags = keywordNodeTypesToTsTypes.get(typeNode.type);
if (keywordTypeFlags) {
return [
{
typeFlags: keywordTypeFlags,
typeName: describeLiteralTypeNode(typeNode),
},
];
}
if (
typeNode.type === AST_NODE_TYPES.TSLiteralType &&
typeNode.literal.type === AST_NODE_TYPES.Literal
) {
return [
{
typeFlags:
primitiveTypeFlagTypes[
typeof typeNode.literal
.value as keyof typeof primitiveTypeFlagTypes
],
typeName: describeLiteralTypeNode(typeNode),
},
];
}
if (typeNode.type === AST_NODE_TYPES.TSUnionType) {
return typeNode.types.flatMap(getTypeNodeTypePartFlags);
}
const nodeType = services.getTypeAtLocation(typeNode);
const typeParts = unionTypePartsUnlessBoolean(nodeType);
return typeParts.map(typePart => ({
typeFlags: typePart.flags,
typeName: describeLiteralType(typePart),
}));
}
- Parameters:
typeNode: TSESTree.TypeNode- Return Type:
TypeFlagsWithName[] - Calls:
keywordNodeTypesToTsTypes.getdescribeLiteralTypeNodetypeNode.types.flatMapservices.getTypeAtLocationunionTypePartsUnlessBooleantypeParts.mapdescribeLiteralType
getTypeNodeTypePartFlagsCached(typeNode: TSESTree.TypeNode): TypeFlagsWithName[]¶
Code
- Parameters:
typeNode: TSESTree.TypeNode- Return Type:
TypeFlagsWithName[] - Calls:
typesCache.getgetTypeNodeTypePartFlagstypesCache.set
checkIntersectionBottomAndTopTypes({ typeFlags, typeName }: TypeFlagsWithName, typeNode: TSESTree.TypeNode): boolean¶
Code
function checkIntersectionBottomAndTopTypes(
{ typeFlags, typeName }: TypeFlagsWithName,
typeNode: TSESTree.TypeNode,
): boolean {
for (const [messageId, checkFlag] of [
['overrides', ts.TypeFlags.Any],
['overrides', ts.TypeFlags.Never],
['overridden', ts.TypeFlags.Unknown],
] as const) {
if (typeFlags === checkFlag) {
context.report({
node: typeNode,
messageId:
typeFlags === ts.TypeFlags.Any && typeName !== 'any'
? 'errorTypeOverrides'
: messageId,
data: {
container: 'intersection',
typeName,
},
});
return true;
}
}
return false;
}
- Parameters:
{ typeFlags, typeName }: TypeFlagsWithNametypeNode: TSESTree.TypeNode- Return Type:
boolean - Calls:
context.report
checkIfUnionsAreAssignable(): undefined¶
Code
(): undefined => {
for (const [typeRef, typeValues] of seenUnionTypes) {
let primitive: number | undefined = undefined;
for (const { typeFlags } of typeValues) {
if (
seenPrimitiveTypes.has(
literalToPrimitiveTypeFlags[
typeFlags as keyof typeof literalToPrimitiveTypeFlags
],
)
) {
primitive =
literalToPrimitiveTypeFlags[
typeFlags as keyof typeof literalToPrimitiveTypeFlags
];
} else {
primitive = undefined;
break;
}
}
if (Number.isInteger(primitive)) {
context.report({
node: typeRef,
messageId: 'primitiveOverridden',
data: {
literal: typeValues.map(name => name.typeName).join(' | '),
primitive:
primitiveTypeFlagNames[
primitive as keyof typeof primitiveTypeFlagNames
],
},
});
}
}
}
- Return Type:
undefined - Calls:
seenPrimitiveTypes.hasNumber.isIntegercontext.reporttypeValues.map(name => name.typeName).join
checkUnionBottomAndTopTypes({ typeFlags, typeName }: TypeFlagsWithName, typeNode: TSESTree.TypeNode): boolean¶
Code
function checkUnionBottomAndTopTypes(
{ typeFlags, typeName }: TypeFlagsWithName,
typeNode: TSESTree.TypeNode,
): boolean {
for (const checkFlag of [
ts.TypeFlags.Any,
ts.TypeFlags.Unknown,
] as const) {
if (typeFlags === checkFlag) {
context.report({
node: typeNode,
messageId:
typeFlags === ts.TypeFlags.Any && typeName !== 'any'
? 'errorTypeOverrides'
: 'overrides',
data: {
container: 'union',
typeName,
},
});
return true;
}
}
if (
typeFlags === ts.TypeFlags.Never &&
!isNodeInsideReturnType(node)
) {
context.report({
node: typeNode,
messageId: 'overridden',
data: {
container: 'union',
typeName: 'never',
},
});
return true;
}
return false;
}
- Parameters:
{ typeFlags, typeName }: TypeFlagsWithNametypeNode: TSESTree.TypeNode- Return Type:
boolean - Calls:
context.reportisNodeInsideReturnType
Interfaces¶
TypeFlagsWithName¶
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
typeFlags |
ts.TypeFlags |
✗ | |
typeName |
string |
✗ |
TypeNodeWithValue¶
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
literalValue |
unknown |
✗ | |
typeNode |
TSESTree.TypeNode |
✗ |
TypeFlagWithText¶
Interface Code
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
literalValue |
unknown |
✗ | |
primitiveTypeFlag |
PrimitiveTypeFlag |
✗ |