absolute/no-trivial-alias
Disallow identity aliases that rename a type or value without transforming it.
#Rule Details
Disallows identity aliases that rename a type or value without transforming it — type X = Y and const x = y. Two names for the same thing drift apart: someone updates one and forgets the other. Pick one name and use it at the consumer.
For types, a bare TSTypeReference with no type arguments, or a bare primitive keyword (a "branded primitive" that forgot the brand), is flagged. Any transformation passes: generic application, unions, intersections, type operators (Pick, Partial, ReturnType, Awaited), template-literal types, indexed access, and object literal types.
For values, an un-annotated const x = y where y resolves to another const binding is flagged. Member-access initializers (const x = obj.foo) are excluded because they can carry meaning, and let/var/parameter sources are skipped because they may be deliberate save-before-mutation captures. Annotated declarations are deferred to no-redundant-type-annotation.
#Examples
type Tag = TagWithCount; // pure rename
type AccountId = string; // branded primitive without the brand
declare const original: number;
const alias = original; // trivial const aliasTransformations are allowed
type Names = Array<string>; // generic application
type Id = string | number; // union
type Summary = Pick<Account, 'id'>; // type operator
type Brand = string & { readonly __brand: 'UserId' }; // real brandingconst value = compute(); // call initializer
const field = config.mode; // member access can carry meaning#Configuration
Enable this rule in your ESLint configuration:
{
rules: {
'absolute/no-trivial-alias': 'error'
}
}#Related Rules
#When Not To Use It
If you use bare aliases as a migration shim (re-pointing a name during a refactor) or to centralize a primitive you plan to brand later, the rule will flag those intentional placeholders — disable it for those lines or files.