Consider the following getSomething()
method:
getSomething<T>(inParameter: string): T {
return null!; // <-- this isn't safe
}
The implementation seems suspect as it claims to return a value of type T
for any type chosen by the caller, with only a string
input. This assertion is unlikely to hold true and cannot easily be verified for type safety.
For instance, calling both
this.getSomething<string>("abc")
and then
this.getSomething<number>("abc")
isn't prevented. Since TypeScript erases types when compiling to JavaScript, both calls will be emitted simply as
this.getSomething("abc")
. As a result, there is no way for the returned value to be both a
string
and a
number
simultaneously, indicating an issue with one of these TypeScript calls.
Now, moving on to your question:
If you directly call this.getSomething(value)
, the inference might fail and T
could default to {}
or `unknown` depending on the TypeScript version.
const hmm = this.getSomething("value"); // const hmm: unknown
// Inference fails, T inferred as unknown
In contrast, if you specify
const t: string = this.getSomething(value)
, contextual typing is utilized to determine that
T
must be
string
:
const t: string = this.getSomething("value");
// Contextual typing, T inferred as string
The recommended approach for both safety and inference is to have the caller provide a parameter of type T
or something capable of producing a value of type T
:
getSomethingReasonable<T>(inParameter: string, tArray: T[]): T {
return tArray[inParameter.length];
}
const okay = this.getSomethingReasonable("value", [1,2,3,4,5,6,7,8]);
// Inference on tArray, T is number
This method is safer since the input tArray
offers a runtime mechanism to produce a value of type
T</code even after type erasure. Moreover, it aids in inferring <code>T
.
Hopefully, this explanation helps. Good luck!
Link to code