Reputation: 53
I have a class with constructor:
class Example<T> {
constructor(private elem: T, private array?: T[]) {}
}
and I want add method some
with returned:
Promise<T>
if not defined param array
in constructorPromise<T[]>
if defined param array
in constructorHow can I do this?
Actualy I have:
class Example<T, S extends T[] | undefined> {
constructor(private elem: T, private array?: S) {}
some(): S extends undefined ? Promise<T> : Promise<S> {
if(!this.array) {
return Promise.resolve(this.elem);
}
return Promise.resolve(this.array);
}
}
const a = new Example(1, undefined);
a.some(); // ✓ Return Promise<number>
const b = new Example(1, [1, 2, 3]);
b.some(); // ✓ Return Promise<number[]>
const c = new Example(1);
c.some(); // ✗ Return Promise<number> | Promise<number[]>, should return Promise<number>
Upvotes: 3
Views: 90
Reputation: 53
After some time I found a solution:
class Example<T, S extends T[] | undefined = undefined> {
constructor(private elem: T, private array?: S) {}
some(): S extends undefined ? Promise<T> : Promise<S> {
if(!this.array) {
return Promise.resolve(this.elem) as any; // [1]
}
return Promise.resolve(this.array) as any; // [1]
}
}
const a = new Example(1, undefined);
a.some(); // ✓ Return Promise<number>
const b = new Example(1, [1, 2, 3]);
b.some(); // ✓ Return Promise<number[]>
const c = new Example(1);
c.some(); // ✓ Return Promise<number>
const d = new Example(1, ["a", "b"]); // ✓ Should be error here
d.some();
[1] Because of issues with conditional type returned type we need to use as any
casting
More elegant should be solution proposed by hackape but it not cover d
case where we expect error
Upvotes: 0
Reputation: 19957
extends
constraint from type parameter S
S extends undefined ?
to S extends T[] ?
class Example<T, S> {
constructor(private elem: T, private array?: S) {}
some(): S extends T[] ? Promise<S> : Promise<T> {
if (!this.array) {
// @ts-ignore
return Promise.resolve(this.elem);
}
// @ts-ignore
return Promise.resolve(this.array);
}
}
const a = new Example(1, undefined);
a.some(); // ✓ Return Promise<number>
const b = new Example(1, [1, 2, 3]);
b.some(); // ✓ Return Promise<number[]>
const c = new Example(1);
c.some(); // ✓ Return Promise<number>
Upvotes: 1