Skip to content

Commit b290d43

Browse files
committed
Add generic type parameter documentation to get_it
- Add explanation of generic type parameter to Accessing Services section - Show how type inference works with inline code examples in Registering Concrete Classes vs Interfaces - Add Switching Implementations subsection with conditional registration pattern - Update testing.md with Pattern 2: Conditional Registration (Alternative) - Rename Pattern 1 to "Scope-Based Testing" - Add explanation about type-based shadowing in testing patterns
1 parent b866f8c commit b290d43

2 files changed

Lines changed: 44 additions & 10 deletions

File tree

docs/documentation/get_it/getting_started.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,21 @@ get_it offers three main registration types:
9090

9191
---
9292

93+
## Accessing Services
94+
95+
The generic type parameter you provide when registering is that one that is used when you access an object after it is registered. **If you don't provide that, Dart will infer it from the implementation type:**
96+
97+
Get your registered services using `getIt<Type>()`:
98+
99+
100+
<<< @/../code_samples/lib/get_it/accessing_services_example.dart#example
101+
102+
::: tip Shorthand Syntax
103+
`getIt<Type>()` is shorthand for `getIt.get<Type>()`. Both work the same - use whichever you prefer!
104+
:::
105+
106+
---
107+
93108
## Registering Concrete Classes vs Interfaces
94109

95110
<strong>Most of the time, register your concrete classes directly:</strong>
@@ -114,18 +129,24 @@ This is simpler and makes IDE navigation to implementation easier.
114129
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Don't use "just because" - creates navigation friction in your IDE</li>
115130
</ul>
116131

117-
---
132+
```dart
133+
// Without type parameter - Dart infers StripePaymentProcessor
134+
getIt.registerSingleton(StripePaymentProcessor());
135+
getIt<PaymentProcessor>(); // ❌️ Error - not registered as PaymentProcessor
118136
119-
## Accessing Services
137+
// With type parameter - explicitly register as PaymentProcessor
138+
getIt.registerSingleton<PaymentProcessor>(StripePaymentProcessor());
139+
getIt<PaymentProcessor>(); // ✅ Works - registered as PaymentProcessor
140+
```
120141

121-
Get your registered services using `getIt<Type>()`:
142+
### Switching Implementations
122143

144+
A common pattern is switching between real and mock implementations using conditional registration:
123145

124-
<<< @/../code_samples/lib/get_it/code_sample_908a2d50.dart#example
125146

126-
::: tip Shorthand Syntax
127-
`getIt<Type>()` is shorthand for `getIt.get<Type>()`. Both work the same - use whichever you prefer!
128-
:::
147+
<<< @/../code_samples/lib/get_it/conditional_registration_example.dart#example
148+
149+
Because both implementations are registered as `<PaymentProcessor>`, the rest of your code remains unchanged - it always requests `getIt<PaymentProcessor>()` regardless of which implementation is registered.
129150

130151
---
131152

docs/documentation/get_it/testing.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,27 @@ Testing code that uses get_it requires different approaches depending on whether
2323

2424
## Unit Testing Patterns
2525

26-
### Pattern 1: Scoped Test Doubles (Recommended)
26+
### Pattern 1: Scope-Based Testing (Recommended)
2727

28-
Use scopes to inject mocks for specific services while keeping the rest of your dependency graph intact.
28+
Use scopes to inject mocks for specific services while keeping the rest of your dependency graph intact. Registering a different implementation in a scope works the same way - using the generic type parameter to shadow the original registration.
2929

3030

3131
<<< @/../code_samples/lib/get_it/main_example_2.dart#example
3232

33-
### Pattern 2: Constructor Injection for Pure Unit Tests
33+
### Pattern 2: Conditional Registration (Alternative)
34+
35+
Instead of using scopes, you can switch implementations at registration time using a flag:
36+
37+
38+
<<< @/../code_samples/lib/get_it/conditional_registration_example.dart#example
39+
40+
This approach is simpler but less flexible than scopes - you must decide which implementation to use before registration, and can't easily switch during runtime.
41+
42+
::: tip Type-Based Shadowing
43+
When you register `MockPaymentProcessor` as `<PaymentProcessor>`, get_it uses the **type parameter** as the lookup key, not the concrete class. This is what enables switching implementations—the same key retrieves different objects in different contexts.
44+
:::
45+
46+
### Pattern 3: Constructor Injection for Pure Unit Tests
3447

3548
For testing classes in complete isolation (without get_it), use optional constructor parameters.
3649

0 commit comments

Comments
 (0)