Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to skip define type on multiple generics class

Tags:

typescript

I have a class with multiple generic properties defined like this:

export class MainClass<
    A = string,
    B = number,
    C = boolean> {
    propA: A
    propB: B
    propC: C
}

It works fine if I fully define 3 types:

let mainClass = new MainClass<string, string, string>

But later I want to create a new instance and only define the 3rd type:

let mainClass2 = new MainClass< , ,custom-type>

Can we omit defining any generic (it gets the default type) and only define the ones we need?

like image 876
Rueta Avatar asked Jan 22 '18 13:01

Rueta


People also ask

How do I restrict a generic type in Java?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.

How do you define a generic type in TypeScript?

Generics allow creating 'type variables' which can be used to create classes, functions & type aliases that don't need to explicitly define the types that they use. Generics makes it easier to write reusable code.

What is type T in TypeScript?

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.

How do I use TypeScript generics?

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.


1 Answers

The only way I can think of is to create subclasses that take different type arguments.

I have illustrated your <,,type> example below. The type annotations are only there to show you what you (effectively) get - you don't need to add the annotations in real life here.

class MainClass<A = string, B = number, C = boolean> {
    propA: A
    propB: B
    propC: C
}

class MainClassB<
    C = boolean> extends MainClass<string, number, C> {
}

let example1: MainClass<string, string, string> = new MainClass<string, string, string>();

let example2: MainClass<string, number, number> = new MainClassB<number>();

The basic concept is that the subclass takes whatever combination of type arguments you want, and returns a class with the three properties of MainClass. You can create various combinations if you want to support the various one or two default situations (eliminating the combinations that can be satisfied by the original type argument order).

Full Example

I have jammed a function in that accepts MainClass to show all the resulting types are structurally compatible:

class MainClass<A = string, B = number, C = boolean> {
    propA: A
    propB: B
    propC: C
}

class MainClassC<C> extends MainClass<string, number, C> {
}

class MainClassAC<A, C> extends MainClass<A, number, C> {
}

class MainClassBC<B, C = boolean> extends MainClass<string, B, C> {
}

function processMainClass(input: MainClass) {
    console.log(input.propA, input.propB, input.propC);
}

let a = new MainClass<string>();
processMainClass(a);

let b = new MainClassBC<number>();
processMainClass(b);

let c = new MainClassC<boolean>();
processMainClass(c);

let ab = new MainClass<string, number>();
processMainClass(ab);

let ac = new MainClassAC<string, boolean>();
processMainClass(ac);

let bc = new MainClassBC<number, boolean>();
processMainClass(bc);

let abc = new MainClass<string, number, boolean>();
processMainClass(abc);
like image 126
Fenton Avatar answered Oct 02 '22 22:10

Fenton