UPDATE
I made a walkaround myself, by move nested type from static field to instane field, which seems to work but was imperfect: https://tsplay.dev/w26Xjw
UPDATE
The main purposes are:
connected/related
So the questions would be:
So that when the user passes the first argument the generic function should restrict the type of the second argument.
Something similar in C++ I'd like to write:
class A {
class InnerType {}
}
template<typename T>
void test(const T& first, const typename T::InnerType& second);
I want to created a generic function which accepts two args:
T
and there would be a nested type T.Param
T.Param
class A {
static Param = class {
....
}
}
class B {
static Param = class {
....
}
}
// How can I make the T/P match the requirements explain above?
function test<T, P>(first:T, second:P) {
}
And then such invoking should pass:
test(new A(), new A.Param()); // OK
test(new A(), new B.Param()); // Fail
test(new B(), new A.Param()); // Fail
test(new B(), new B.Param()); // OK
A Generic Version of the Box Class To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.
Assigning Generic Parameters By passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
This article opts to use the term type variables, coinciding with the official Typescript documentation. T stands for Type, and is commonly used as the first type variable name when defining generics. But in reality T can be replaced with any valid name.
There are a couple of different ways to do it, depending in part on which argument you want to drive the process. You can drive it with the first argument:
function test1<T extends {Param: unknown}, P extends T["Param"]>(first: T, second: P) {
// ...
}
or the second:
function test2<P, T extends {Param: P}>(first: T, second: P) {
// ...
}
With those, you get these results:
test1(A, A.Param); // works
test1(B, A.Param); // error on second argument
test2(A, A.Param); // works
test2(B, A.Param); // error on first argument
Playground with both
Note that because TypeScript's type system is structural (based on the shapes of types) rather than nominal (based on the names of types), in the playground link I added things to A.Param
and B.Param
so they wouldn't have the same shape. Otherwise, since their shapes are the same (empty classes), either can be used in place of the other.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With