In the follow example, getValue function
can not get the correct type.
Is there any way to infer type by configurable settings?
Example Play
For example
class User {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Cat {
name: string;
constructor(name: string) {
this.name = name;
}
}
const settings = [
{ key: 'a', value: 'string' },
{ key: 'b', value: 123 },
{ key: 'c', value: true },
{ key: 'dog', value: Dog },
{ key: 'cat', value: Cat },
{ key: Dog, value: Cat },
{ key: Cat, value: Dog },
{ key: User, value: User },
]
function getValue(key: any) {
const item = settings.find(obj => obj.key === key);
if (item) {
const { value } = item
if (typeof value === 'function') {
return new value('test value');
} else {
return value;
}
} else {
throw new Error('not found');
}
}
Of course, I can use as Dog
to force cast type.
const dog = getValue('dog') as Dog;
But I think it is a bit redundant.
Is there any better way to solve this problem?
---edit 2020-10-20---
In fact, the settings
is not pre-defined.
It could be modified in the runtime.
Finally I want to implement a function like angular dependency injection function.
The settings's
structure is like this:
[
{provide: User, useValue: new User('Tom')},
{provide: Cat, useClass: Cat},
{provide: Dog, useClass: Dog},
{provide: AnotherDog, useExiting: Dog},
{provide: AnotherCat, useFactory: function(user) { return user.cat; }, deps: [User]},
]
And the settings
is not pre-defined. It could be modified in the runtime.
eg.
let settings = [
{ key: Cat, value: Cat },
{ key: Dog, value: Dog },
]
const cat1 = getValue(Cat); // cat1 is Cat
const dog1 = getValue(Dog); // dog1 is Dog
settings = [
{ key: Cat, value: Dog },
{ key: Dog, value: Cat },
]
const cat2 = getValue(Cat); // cat2 is Dog
const dog2 = getValue(Dog); // dog2 is Cat
That's what I mean settings could be modified in the runtime.
eg.2
let settings = [
{ key: Cat, value: Cat },
{ key: Dog, value: Dog },
]
// cat1 is Cat, getValue return type default as Parameter Cat
const cat1 = getValue(Cat);
// dog1 is Dog, getValue return type default as Parameter Dog
const dog1 = getValue(Dog);
settings = [
{ key: Cat, value: Dog },
{ key: Dog, value: Cat },
]
// cat2 is Dog, getValue return type is set by generic type Dog
const cat2 = getValue<Dog>(Cat);
// dog2 is Cat, getValue return type is set by generic type Cat
const dog2 = getValue<Cat>(Dog);
Can getValue function be implemented like this by optional generic type?