@@ -63,6 +63,45 @@ Rules:
6363- Implementations do not become tokens by extending or implementing a contract;
6464 only the decorated class itself is a token.
6565
66+ Tokens for non-classes: ` InjectionToken `
67+ ----------------------------------------
68+
69+ Some registrations have no class to decorate — an imported module namespace, a
70+ plain value, a function. ` InjectionToken ` is the typed key for those:
71+
72+ ``` ts
73+ import { InjectionToken , inject } from " nativescript/contracts" ;
74+
75+ export const XCODE = new InjectionToken <typeof import (" nativescript-dev-xcode" )>(
76+ " xcode" ,
77+ );
78+
79+ class ProjectPatcher {
80+ private xcode = inject (XCODE ); // typeof import("nativescript-dev-xcode")
81+ }
82+ ```
83+
84+ The description ** is** the registry name, exactly as a contract's name is, so a
85+ token is a typed alias onto an existing registration and nothing has to change
86+ where the value is registered — ` injector.register("xcode", xcode) ` keeps
87+ serving ` inject(XCODE) ` . A leading ` $ ` in the description is stripped.
88+
89+ Names are minted in the same registry ` @Contract ` uses, so a token and a
90+ contract cannot claim the same name: the second one ** throws at load time** ,
91+ rather than silently aliasing one registration under two tokens.
92+
93+ Tokens are used anywhere a contract class is — ` inject() ` , ` get() ` , ` provide() `
94+ and the provider literals:
95+
96+ ``` ts
97+ { provide : XCODE , useValue : xcode }
98+ { provide : XCODE , useFactory : () => require (" nativescript-dev-xcode" ) }
99+ ```
100+
101+ Prefer a ` @Contract ` class when the dependency is a service: it also carries
102+ the service's shape. Reach for ` InjectionToken ` only when there is nothing to
103+ decorate.
104+
66105Resolving: ` inject() ` and ` Injector `
67106------------------------------------
68107
@@ -90,10 +129,10 @@ class EnvironmentChecker {
90129}
91130```
92131
93- ` Injector.get() ` accepts a contract class, a string name, or a ` $ ` -prefixed
94- string name — all three return the same instance. The string forms exist for
95- interoperability with the legacy registry; use the class token whenever one
96- exists.
132+ ` Injector.get() ` accepts a contract class, an ` InjectionToken ` , a string name,
133+ or a ` $ ` -prefixed string name — all of them return the same instance. The
134+ string forms exist for interoperability with the legacy registry; use the token
135+ whenever one exists.
97136
98137Both ` inject() ` and ` get() ` take Angular-shaped options as their second
99138argument:
@@ -155,7 +194,8 @@ instance. Transient instances are still retained by the container so
155194String keys are accepted anywhere a token is (` { provide: "logger", useValue } ` )
156195— that is how the legacy facade registers, and how per-call overrides address
157196not-yet-migrated dependencies. New registrations should mint a ` @Contract `
158- token instead of a new string name.
197+ class, or an ` InjectionToken ` when there is no class to decorate, instead of a
198+ new string name.
159199
160200For per-call construction with overrides (a fresh instance of a class with some
161201dependencies replaced), use ` createInstance ` :
@@ -173,16 +213,17 @@ owns them and never see the per-call providers.
173213Resolution semantics
174214--------------------
175215
176- - Lookup is ** class object first, token name on a miss** , checked per injector
177- level before delegating to the parent. Both keys index the same provider
178- record, so re-registering a service by its string name (as plugins are
179- documented to do with ` $logger ` ) stays visible to ` inject(Logger) ` consumers.
216+ - Lookup is ** token identity first, token name on a miss** , checked per
217+ injector level before delegating to the parent. Both keys index the same
218+ provider record, so re-registering a service by its string name (as plugins
219+ are documented to do with ` $logger ` ) stays visible to ` inject(Logger) `
220+ consumers. This holds for ` @Contract ` classes and ` InjectionToken ` s alike.
180221- A leading ` $ ` is stripped from string tokens: ` get("$fs") ` and ` get("fs") `
181222 are the same registration.
182- - The name fallback also makes ** duplicated contract copies interchangeable** :
183- if an extension's dependency tree carries its own copy of a contract class,
184- that copy resolves to the same provider by name. "Works locally, breaks when
185- installed" is not a failure mode of this design.
223+ - The name fallback also makes ** duplicated token copies interchangeable** : if
224+ an extension's dependency tree carries its own copy of a contract class or
225+ injection token, that copy resolves to the same provider by name. "Works
226+ locally, breaks when installed" is not a failure mode of this design.
186227- Cyclic dependencies fail with the full resolution path
187228 (` Cyclic dependency detected on dependency 'a'. Resolution path: a -> b -> a ` ).
188229
@@ -284,6 +325,13 @@ contract and every existing caller sees it.
284325| ` Prompter ` | ` prompter ` |
285326| ` TempService ` | ` tempService ` |
286327
328+ And the injection tokens, for registrations that are not classes:
329+
330+ | Token | Legacy name | Value |
331+ | ---| ---| ---|
332+ | ` XCODE ` | ` xcode ` | the ` nativescript-dev-xcode ` module |
333+ | ` PBXPROJ_DOM_XCODE ` | ` pbxprojDomXcode ` | the ` pbxproj-dom/xcode ` module |
334+
287335Related guides
288336--------------
289337
0 commit comments