DEV Community

Mikhail Potapov
Mikhail Potapov

Posted on

🔥 Naming Interfaces in TypeScript: IUser vs User

In TypeScript, it is common for developers to prefix their interfaces with "I" (e.g., IUser) following the Hungarian notation. However, not all developers adhere to this convention.

I used to prefer using the "I" prefix for my interfaces as I believed it improved the reliability and clarity of my code. I also extended this convention to types, like TUser.

However, I encountered an issue when I needed to convert some interfaces into types, specifically when my interface became a union type of other interfaces. This necessitated replacing all the "I" prefixes with "T" throughout the codebase. These changes proved to be cumbersome, unnecessary. This issue has occurred multiple times for me and my colleagues, leading us to abandon the use of the "I" prefix.

I would like to know your thoughts on this matter. Do you also use prefixes for your interfaces?

Top comments (10)

Collapse
 
ant_f_dev profile image
Anthony Fung

I don't think it's Hungarian notation as such - more C# convention. The typical Hungarian notation is more like iCount (for int), dwRadius (for double), szUsername (for string), lMilliseconds (for long).

I still prefix interfaces with I out of habit, but I did notice that the TypeScript handbook shows an example of interface declaration without the prefix. That said, I'm sure there was an I in earlier examples of the language.

All things considered, I'd probably say consistency is the most important thing. If your project already uses I, keep doing so or do a refactor to remove it everywhere (resource-permitting). When working on new projects, it might be best to go without.

Collapse
 
haaxor1689 profile image
Maroš Beťko

Step one, stop using interfaces and use types only. Apart from module augmentation, which should basically only be used by libraries anyway, there is nothing types can't do that interfaces can.

What you can also do with types is to name them the same as the value they represent and typescript will know which to use based on context. It's useful for use cases like zod schemas.

export const MyShema = z.object({ ... });
export type MySchema z.infer<typeof MySchema>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
intrnl profile image
intrnl • Edited

Note that this can be very disastrous if parts of your app (like on a monorepo) generates type declarations for consumption

It's heavily preferred to use interfaces over types if so

I think it might've been fixed already but it's still worth noting anyways, I personally prefer interfaces when able to because it's explicitly clear

Collapse
 
haaxor1689 profile image
Maroš Beťko

Oh damn, didn't know about this bug. Still it's just a temporary workaround and not something I'd switch over to using combination of types and interfaces.

Collapse
 
matthewdean profile image
Matthew Dean • Edited

The official TypeScript style guide says to not use I for interfaces for a number of reasons. Another reason is that class definitions can serve as types, so it can quickly become inconsistent. If someone is using “I” for interfaces, they’re probably coming from C# and have misunderstandings about TS/JS.

Collapse
 
cmcnicholas profile image
Craig McNicholas

I avoid using prefixes for anything. It's refactoring hell when you have to change those types and there is no real way to guard against inconsistency.

The real question is "why do I need to know?", there's very few occasions where you need to know what you're working with is an interface or concrete (and it should be an interface anyway) if you're following SOLID which if you're using OO you should be considering anyway.

Collapse
 
thegrimsilence profile image
Grim • Edited

I prefix interfaces only. When I first started coding I used IUser, TUser, EUserRole, but it all became redundant eventually. So now I use interfaces for everything until it needs to be a type. I prefix all interfaces with I, as in my book Interfaces are to be implemented but not just tossed around. Type are for unions and generics, enums are for a selection of limited values. And I never use class definitions as types if it can be avoided as that’s what interfaces are for.

But I prefer DI, so I usually use the interfaces to give the types needed from an injected service.

But I’ve spent 3 years tearing apart VS Code’s repo and learning programming that way as a real world example vs tutorial hell.

Collapse
 
nathanelcorpuz profile image
Nathanel

This is very interesting. I am new to TypeScript (2 weeks), and saw npm libraries use the IUser convention.

Collapse
 
fardelian profile image
Florin

That's when you're supposed to use your IDEs refactoring functionality

Collapse
 
bwca profile image
Volodymyr Yepishev

It depends, I go with what the team decides to go, but my personal preference is not having the I prefix, since it's what contributors to typescript choose, though I am not among their numbers.