eslint-plugin-functional
Version:
ESLint rules to promote functional programming in TypeScript.
643 lines (642 loc) • 25.3 kB
text/typescript
import { FlatConfig, ReportDescriptor, RuleListener, RuleContext } from "@typescript-eslint/utils/ts-eslint";
import { NamedCreateRuleMeta } from "@typescript-eslint/utils/eslint-utils";
import { ImmutabilityOverrides, Immutability } from "is-immutable-type";
import { Type, TypeNode } from "typescript";
import { Node as TSNode } from "typescript";
import { TSESTree } from "@typescript-eslint/utils";
import { JSONSchema4ObjectSchema } from "@typescript-eslint/utils/json-schema";
declare namespace typeDeclarationImmutability {
type ESFunction = TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression;
type ESFunctionType = ESFunction | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSDeclareFunction | TSESTree.TSEmptyBodyFunctionExpression | TSESTree.TSFunctionType | TSESTree.TSMethodSignature;
type ESClass = TSESTree.ClassDeclaration | TSESTree.ClassExpression;
type ESLoop = TSESTree.DoWhileStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.ForStatement | TSESTree.WhileStatement;
type ESArrayTupleType = TSESTree.TSArrayType | TSESTree.TSTupleType;
type ESProperty = TSESTree.PropertyDefinition | TSESTree.TSIndexSignature | TSESTree.TSParameterProperty | TSESTree.TSPropertySignature;
type ESTypeDeclaration = TSESTree.TSInterfaceDeclaration | TSESTree.TSTypeAliasDeclaration;
/**
* Any custom rule meta properties.
*/
type NamedCreateRuleCustomMeta<T extends string, Options extends BaseOptions> = Omit<NamedCreateRuleMeta<T, Options>, "docs"> & {
docs: {
/**
* Used for creating category configs and splitting the README rules list into sub-lists.
*/
category: "Currying" | "No Exceptions" | "No Mutations" | "No Other Paradigms" | "No Statements" | "Stylistic";
recommended: "recommended" | "strict" | false;
recommendedSeverity: "error" | "warn";
} & Omit<NamedCreateRuleMeta<T, Options>["docs"], "recommended">;
};
/**
* All options must extends this type.
*/
type BaseOptions = ReadonlyArray<unknown>;
type RuleDefinition<MessageIds extends string, Options extends BaseOptions> = {
readonly defaultOptions: Options;
readonly meta: NamedCreateRuleCustomMeta<MessageIds, Options>;
readonly create: (context: Readonly<RuleContext<MessageIds, Options>>) => RuleListener;
};
/**
* The result all rules return.
*/
type RuleResult<MessageIds extends string, Options extends BaseOptions> = Readonly<{
context: Readonly<RuleContext<MessageIds, Options>>;
descriptors: ReadonlyArray<ReportDescriptor<MessageIds>>;
}>;
/**
* A map of nodes to functions that a rule operate on.
*/
type RuleFunctionsMap<Node extends TSESTree.Node, MessageIds extends string, Options extends BaseOptions> = Readonly<{
[ ]: (node: Node, context: RuleContext<MessageIds, Options>, options: Options) => RuleResult<MessageIds, Options>;
}>;
/* eslint-enable functional/no-return-void, functional/no-expression-statements */
/**
* Create a rule.
*/
function createRule<MessageIds extends string, Options extends BaseOptions>(name: string, meta: NamedCreateRuleCustomMeta<MessageIds, Options>, defaultOptions: Options, ruleFunctionsMap: RuleFunctionsMap<any, MessageIds, Options>): RuleDefinition<MessageIds, Options>;
/**
* Create a rule.
*/
function createRuleUsingFunction<MessageIds extends string, Options extends BaseOptions>(name: string, meta: NamedCreateRuleCustomMeta<MessageIds, Options>, defaultOptions: Options, createFunction: (context: Readonly<RuleContext<MessageIds, Options>>, options: Readonly<Options>) => RuleFunctionsMap<any, MessageIds, Options>): RuleDefinition<MessageIds, Options>;
/**
* Get the type of the the given node.
*/
function getTypeOfNode<Context extends RuleContext<string, BaseOptions>>(node: TSESTree.Node, context: Context): Type;
/**
* Get the type of the the given ts node.
*/
function getTypeOfTSNode<Context extends RuleContext<string, BaseOptions>>(node: TSNode, context: Context): Type;
/**
* Get the return type of the the given function node.
*/
function getReturnTypesOfFunction<Context extends RuleContext<string, BaseOptions>>(node: TSESTree.Node, context: Context): Type[] | null;
/**
* Does the given function have overloads?
*/
function isImplementationOfOverload<Context extends RuleContext<string, BaseOptions>>(func: ESFunction, context: Context): boolean;
/**
* Get the type immutability of the the given node or type.
*/
function getTypeImmutabilityOfNode<Context extends RuleContext<string, BaseOptions>>(node: TSESTree.Node, context: Context, maxImmutability?: Immutability, explicitOverrides?: ImmutabilityOverrides): Immutability;
/**
* Get the type immutability of the the given type.
*/
function getTypeImmutabilityOfType<Context extends RuleContext<string, BaseOptions>>(typeOrTypeNode: Type | TypeNode, context: Context, maxImmutability?: Immutability, explicitOverrides?: ImmutabilityOverrides): Immutability;
/**
* Get the es tree node from the given ts node.
*/
function getESTreeNode<Context extends Readonly<RuleContext<string, BaseOptions>>>(node: TSNode, context: Context): TSESTree.Node | null;
/**
* The option to ignore patterns.
*/
type IgnoreIdentifierPatternOption = Readonly<{
ignoreIdentifierPattern?: ReadonlyArray<string> | string;
}>;
/**
* The schema for the option to ignore patterns.
*/
const ignoreIdentifierPatternOptionSchema: JSONSchema4ObjectSchema["properties"];
/**
* The option to ignore patterns.
*/
type IgnoreCodePatternOption = Readonly<{
ignoreCodePattern?: ReadonlyArray<string> | string;
}>;
/**
* The schema for the option to ignore patterns.
*/
const ignoreCodePatternOptionSchema: JSONSchema4ObjectSchema["properties"];
/**
* The option to ignore accessor patterns.
*/
type IgnoreAccessorPatternOption = Readonly<{
ignoreAccessorPattern?: ReadonlyArray<string> | string;
}>;
/**
* The schema for the option to ignore accessor patterns.
*/
const ignoreAccessorPatternOptionSchema: JSONSchema4ObjectSchema["properties"];
/**
* The option to ignore classes.
*/
type IgnoreClassesOption = Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}>;
/**
* The schema for the option to ignore classes.
*/
const ignoreClassesOptionSchema: JSONSchema4ObjectSchema["properties"];
/**
* The option to ignore prefix selector.
*/
type IgnorePrefixSelectorOption = Readonly<{
ignorePrefixSelector?: ReadonlyArray<string> | string;
}>;
/**
* The schema for the option to ignore prefix selector.
*/
const ignorePrefixSelectorOptionSchema: JSONSchema4ObjectSchema["properties"];
/**
* Should the given node be allowed base off the following rule options?
*
* - AllowInFunctionOption.
*/
function shouldIgnoreInFunction(node: TSESTree.Node, context: Readonly<RuleContext<string, BaseOptions>>, allowInFunction: boolean | undefined): boolean;
/**
* Should the given node be allowed base off the following rule options?
*
* - IgnoreClassesOption.
*/
function shouldIgnoreClasses(node: TSESTree.Node, context: Readonly<RuleContext<string, BaseOptions>>, ignoreClasses: Readonly<Partial<IgnoreClassesOption>["ignoreClasses"]>): boolean;
/**
* Should the given node be allowed base off the following rule options?
*
* - IgnoreAccessorPatternOption.
* - IgnoreIdentifierPatternOption.
*/
function shouldIgnorePattern(node: TSESTree.Node, context: Readonly<RuleContext<string, BaseOptions>>, ignoreIdentifierPattern: Readonly<Partial<IgnoreIdentifierPatternOption>["ignoreIdentifierPattern"]>, ignoreAccessorPattern?: Readonly<Partial<IgnoreAccessorPatternOption>["ignoreAccessorPattern"]>, ignoreCodePattern?: Readonly<Partial<IgnoreCodePatternOption>["ignoreCodePattern"]>): boolean;
/**
* The name of this rule.
*/
const name = "type-declaration-immutability";
/**
* The full name of this rule.
*/
const fullName = "functional/type-declaration-immutability";
/**
* How the actual immutability should be compared to the given immutability.
*/
enum RuleEnforcementComparator {
Less = -2,
AtMost = -1,
Exactly = 0,
AtLeast = 1,
More = 2
}
type FixerConfigRaw = {
pattern: string;
replace: string;
};
type FixerConfig = {
pattern: RegExp;
replace: string;
};
type SuggestionsConfig = FixerConfig[];
/**
* The options this rule can take.
*/
type Options = [
IgnoreIdentifierPatternOption & {
rules: Array<{
identifiers: string | string[];
immutability: Exclude<Immutability | keyof typeof Immutability, "Unknown">;
comparator?: RuleEnforcementComparator | keyof typeof RuleEnforcementComparator;
fixer?: FixerConfigRaw | FixerConfigRaw[] | false;
suggestions?: FixerConfigRaw[] | false;
}>;
ignoreInterfaces: boolean;
}
];
/**
* A rule given by the user after being upgraded.
*/
type ImmutabilityRule = {
identifiers: RegExp[];
immutability: Immutability;
comparator: RuleEnforcementComparator;
fixers: FixerConfig[] | false;
suggestions: SuggestionsConfig | false;
};
// Create the rule.
const rule: RuleDefinition<"Less" | "AtMost" | "Exactly" | "AtLeast" | "More", Options>;
}
type ESFunction = TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression;
/**
* Any custom rule meta properties.
*/
type NamedCreateRuleCustomMeta<T extends string, Options extends BaseOptions> = Omit<NamedCreateRuleMeta<T, Options>, "docs"> & {
docs: {
/**
* Used for creating category configs and splitting the README rules list into sub-lists.
*/
category: "Currying" | "No Exceptions" | "No Mutations" | "No Other Paradigms" | "No Statements" | "Stylistic";
recommended: "recommended" | "strict" | false;
recommendedSeverity: "error" | "warn";
} & Omit<NamedCreateRuleMeta<T, Options>["docs"], "recommended">;
};
/**
* All options must extends this type.
*/
type BaseOptions = ReadonlyArray<unknown>;
type RuleDefinition<MessageIds extends string, Options extends BaseOptions> = {
readonly defaultOptions: Options;
readonly meta: NamedCreateRuleCustomMeta<MessageIds, Options>;
readonly create: (context: Readonly<RuleContext<MessageIds, Options>>) => RuleListener;
};
/**
* The result all rules return.
*/
type RuleResult<MessageIds extends string, Options extends BaseOptions> = Readonly<{
context: Readonly<RuleContext<MessageIds, Options>>;
descriptors: ReadonlyArray<ReportDescriptor<MessageIds>>;
}>;
/**
* A map of nodes to functions that a rule operate on.
*/
type RuleFunctionsMap<Node extends TSESTree.Node, MessageIds extends string, Options extends BaseOptions> = Readonly<{
[ ]: (node: Node, context: RuleContext<MessageIds, Options>, options: Options) => RuleResult<MessageIds, Options>;
}>;
/**
* All of the custom rules.
*/
declare const rules: {
"functional-parameters": RuleDefinition<"arguments" | "restParam" | "paramCountAtLeastOne" | "paramCountExactlyOne", [
Readonly<{
ignoreIdentifierPattern?: string | readonly string[];
}> & Readonly<{
ignorePrefixSelector?: string | readonly string[];
}> & {
allowRestParameter: boolean;
allowArgumentsKeyword: boolean;
enforceParameterCount: false | ("atLeastOne" | "exactlyOne") | {
count: "atLeastOne" | "exactlyOne";
ignoreLambdaExpression: boolean;
ignoreIIFE: boolean;
ignoreGettersAndSetters: boolean;
};
}
]>;
"immutable-data": RuleDefinition<"object" | "array" | "generic", [
Readonly<{
ignoreAccessorPattern?: string | readonly string[];
}> & Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}> & Readonly<{
ignoreIdentifierPattern?: string | readonly string[];
}> & {
ignoreImmediateMutation: boolean;
ignoreNonConstDeclarations: boolean | {
treatParametersAsConst: boolean;
};
}
]>;
"no-classes": RuleDefinition<"generic", [
{}
]>;
"no-conditional-statements": RuleDefinition<"incompleteBranch" | "incompleteIf" | "incompleteSwitch" | "unexpectedIf" | "unexpectedSwitch", [
{
allowReturningBranches: boolean | "ifExhaustive";
}
]>;
"no-expression-statements": RuleDefinition<"generic", [
Readonly<{
ignoreCodePattern?: string | readonly string[];
}> & {
ignoreVoid: boolean;
ignoreSelfReturning: boolean;
}
]>;
"no-let": RuleDefinition<"generic", [
Readonly<{
ignoreIdentifierPattern?: string | readonly string[];
}> & {
allowInForLoopInit: boolean;
allowInFunctions: boolean;
}
]>;
"no-loop-statements": RuleDefinition<"generic", [
{}
]>;
"no-mixed-types": RuleDefinition<"generic", [
{
checkInterfaces: boolean;
checkTypeLiterals: boolean;
}
]>;
"no-promise-reject": RuleDefinition<"generic", [
{}
]>;
"no-return-void": RuleDefinition<"generic", [
{
allowNull: boolean;
allowUndefined: boolean;
ignoreInferredTypes: boolean;
}
]>;
"no-this-expressions": RuleDefinition<"generic", [
{}
]>;
"no-throw-statements": RuleDefinition<"generic", [
{
allowInAsyncFunctions: boolean;
}
]>;
"no-try-statements": RuleDefinition<"catch" | "finally", [
{
allowCatch: boolean;
allowFinally: boolean;
}
]>;
"prefer-immutable-types": RuleDefinition<"returnType" | "parameter" | "variable" | "propertyImmutability" | "propertyModifier", [
Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}> & {
enforcement: false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None";
ignoreInferredTypes: boolean;
ignoreNamePattern?: string | string[];
ignoreTypePattern?: string | string[];
} & {
parameters?: (false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None") | Partial<Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}> & {
enforcement: false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None";
ignoreInferredTypes: boolean;
ignoreNamePattern?: string | string[];
ignoreTypePattern?: string | string[];
}>;
returnTypes?: (false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None") | Partial<Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}> & {
enforcement: false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None";
ignoreInferredTypes: boolean;
ignoreNamePattern?: string | string[];
ignoreTypePattern?: string | string[];
}>;
variables?: (false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None") | Partial<Readonly<{
ignoreClasses: boolean | "fieldsOnly";
}> & {
enforcement: false | import("is-immutable-type").Immutability | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating" | "None";
ignoreInferredTypes: boolean;
ignoreNamePattern?: string | string[];
ignoreTypePattern?: string | string[];
} & {
ignoreInFunctions?: boolean;
}>;
fixer?: Partial<Record<"ReadonlyShallow" | "ReadonlyDeep" | "Immutable", {
pattern: string;
replace: string;
} | {
pattern: string;
replace: string;
}[] | undefined>>;
suggestions?: Partial<Record<"ReadonlyShallow" | "ReadonlyDeep" | "Immutable", {
pattern: string;
replace: string;
}[][] | undefined>>;
}
]>;
"prefer-property-signatures": RuleDefinition<"generic", [
{
ignoreIfReadonlyWrapped: boolean;
}
]>;
"prefer-readonly-type": RuleDefinition<"type" | "array" | "property" | "implicit" | "tuple", [
{
allowLocalMutation: boolean;
allowMutableReturnType: boolean;
checkImplicit: boolean;
ignoreCollections: boolean;
ignoreClass: boolean | "fieldsOnly";
ignoreInterface: boolean;
ignorePattern?: string | string[];
}
]>;
"prefer-tacit": RuleDefinition<"generic", [
{
checkMemberExpressions: boolean;
}
]>;
"readonly-type": RuleDefinition<"generic" | "keyword", [
"generic" | "keyword"
]>;
"type-declaration-immutability": RuleDefinition<"Less" | "AtMost" | "Exactly" | "AtLeast" | "More", [
Readonly<{
ignoreIdentifierPattern?: string | readonly string[];
}> & {
rules: {
identifiers: string | string[];
immutability: import("is-immutable-type").Immutability | "Mutable" | "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Calculating";
comparator?: typeDeclarationImmutability.RuleEnforcementComparator | "Less" | "AtMost" | "Exactly" | "AtLeast" | "More";
fixer?: false | {
pattern: string;
replace: string;
} | {
pattern: string;
replace: string;
}[];
suggestions?: false | {
pattern: string;
replace: string;
}[];
}[];
ignoreInterfaces: boolean;
}
]>;
};
declare const meta: {
readonly name: "eslint-plugin-functional";
readonly version: "0.0.0-development";
};
declare const configs: {
all: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
lite: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
"functional/functional-parameters": ["error", {
enforceParameterCount: boolean;
}];
"functional/immutable-data": ["error", {
ignoreClasses: string;
}];
"functional/no-conditional-statements": "off";
"functional/no-expression-statements": "off";
"functional/prefer-immutable-types": ["error", {
enforcement: string;
ignoreInferredTypes: boolean;
parameters: {
enforcement: string;
};
}];
"functional/no-let": ["error", {
allowInForLoopInit: boolean;
}];
"functional/no-this-expressions": "off";
"functional/no-throw-statements": ["error", {
allowInAsyncFunctions: boolean;
}];
"functional/no-try-statements": "off";
"functional/type-declaration-immutability": ["error", {
rules: ({
identifiers: string[];
immutability: import("is-immutable-type").Immutability;
comparator: RuleEnforcementComparator;
suggestions?: never;
} | {
identifiers: string[];
immutability: import("is-immutable-type").Immutability;
comparator: RuleEnforcementComparator;
suggestions: {
pattern: string;
replace: string;
}[];
})[];
}];
};
};
recommended: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
"functional/functional-parameters": ["error", {
enforceParameterCount: {
ignoreLambdaExpression: boolean;
ignoreIIFE: boolean;
ignoreGettersAndSetters: boolean;
};
}];
"functional/no-conditional-statements": ["error", {
allowReturningBranches: boolean;
}];
"functional/no-let": ["error", {
allowInForLoopInit: boolean;
}];
"functional/no-this-expressions": "off";
"functional/no-throw-statements": ["error", {
allowInAsyncFunctions: boolean;
}];
"functional/no-try-statements": "off";
"functional/prefer-immutable-types": ["error", {
enforcement: string;
ignoreInferredTypes: boolean;
parameters: {
enforcement: string;
};
}];
"functional/type-declaration-immutability": ["error", {
rules: ({
identifiers: string[];
immutability: import("is-immutable-type").Immutability;
comparator: RuleEnforcementComparator;
suggestions?: never;
} | {
identifiers: string[];
immutability: import("is-immutable-type").Immutability;
comparator: RuleEnforcementComparator;
suggestions: {
pattern: string;
replace: string;
}[];
})[];
}];
};
};
strict: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
off: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "off";
};
};
disableTypeChecked: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "off";
};
};
externalVanillaRecommended: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
"prefer-const": "error";
"no-param-reassign": "error";
"no-var": "error";
};
};
externalTypescriptRecommended: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
"@typescript-eslint/prefer-readonly": "error";
"@typescript-eslint/switch-exhaustiveness-check": "error";
"prefer-const": "error";
"no-param-reassign": "error";
"no-var": "error";
};
};
currying: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
noExceptions: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
noMutations: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
noOtherParadigms: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
noStatements: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
stylistic: {
plugins: {
functional: FlatConfig.Plugin;
};
rules: {
[ ]: "error" | "warn";
};
};
};
declare const _default: FlatConfig.Plugin & {
meta: typeof meta;
rules: typeof rules;
configs: typeof configs;
};
export { _default as default };