If you want the compiler to automatically determine the type string
for the generic type parameter T
, you will need to modify your code. This behavior only occurs when you call a generic function, so you'll have to refactor from using a type annotation (
const test: MyObject<string> = ...
) to calling a helper function (
const test = toMyObject(...)
).
Update for TS4.7+:
In TypeScript 4.7+, it seems that microsoft/TypeScript#48358 will introduce the ability for the compiler to contextualize type method parameters based on inferred type parameters from earlier defined properties. With this enhancement, the following code snippet will work:
const toMyObject = <T,>(o: MyObject<T>) => o;
let test = toMyObject({
create() {
return "Hello"
},
update(value) {
value.toUpperCase()
},
})
Note that the order of members in the object literal is crucial for this inference to work correctly. Therefore, make sure that T
is inferred from create()
before using it in update()
. An incorrect order like the one below will cause an error:
let test2 = toMyObject({
update(value) {
value.toUpperCase() // error
},
create() {
return "Hello"
},
});
Playground link for TS4.7+
Previous answer for TS4.6-:
Additionally, if you need the compiler to infer the type of the callback parameter value
in the update
method, you should be aware of contextual typing. Unfortunately, in TypeScript, contextual type inference of callback parameters and generic type parameter inference might conflict when both rely on the same object. Refer to microsoft/TypeScript#38872 for more details.
To achieve both types of inference, split the input object into two parts within your helper function: one handling create
for inferring the generic type parameter T
, and the other dealing with update
to allow inference of the callback parameter value
's type.
This results in the following code:
const toMyObject = <T,>(
create: () => T,
update: (value: T) => void
): MyObject<T> => ({ create, update });
Let's try it out:
let test = toMyObject(
() => { return "Hello" },
(value) => { console.log(value.toUpperCase()); }
);
// let test: MyObject<string>
It appears to be working fine. The compiler determines that test
is of type
MyObject<string></code as expected, and the callback parameter <code>value
is also inferred as
string
(as shown by the fact that
value.toUpperCase()
can be called without any errors in
--strict
mode).
Playground link to code for TS4.6-