📄 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: Key
value: Value
- Return Type:
void
- Calls:
map.get
existing.push
map.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.isStringLiteral
JSON.stringify
isTypeBigIntLiteralType (from ../util)
type.isLiteral
type.value.toString
tsutils.isIntrinsicErrorType
type.aliasSymbol.escapedName.toString
isTypeAnyType (from ../util)
isTypeNeverType (from ../util)
isTypeUnknownType (from ../util)
isTypeTemplateLiteralType (from ../util)
tsutils.isTrueLiteralType
tsutils.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.isUnion
tsutils.isFalseLiteralType
tsutils.isTrueLiteralType
tsutils.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.get
describeLiteralTypeNode
typeNode.types.flatMap
services.getTypeAtLocation
unionTypePartsUnlessBoolean
typeParts.map
describeLiteralType
getTypeNodeTypePartFlagsCached(typeNode: TSESTree.TypeNode): TypeFlagsWithName[]
¶
Code
- Parameters:
typeNode: TSESTree.TypeNode
- Return Type:
TypeFlagsWithName[]
- Calls:
typesCache.get
getTypeNodeTypePartFlags
typesCache.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 }: TypeFlagsWithName
typeNode: 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.has
Number.isInteger
context.report
typeValues.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 }: TypeFlagsWithName
typeNode: TSESTree.TypeNode
- Return Type:
boolean
- Calls:
context.report
isNodeInsideReturnType
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 |
✗ |