我有一个enum DataType { NUMBER, STRING }
和一个对象。
我希望TypeScript理解example.id
是number
(而不是DataType.NUMBER
),同样,通过泛型converter()
函数,example.name
被视为string
而不是DataType.STRING
。
不需要实现该函数,只需根据传递的参数进行type
推理即可:
function converter(...): infer type here { ... }
const example = converter({ id: DataType.NUMBER, name: DataType.STRING });
ts.typeof example.id === number
ts.typeof example.name === string
我的目标是用户应该传递一个数据模型(“模式”),函数将返回一个与数据模型兼容的值,类似于ORM。
class Model {
public get(... columns: string[]) {
// ...
}
}
class User extends Model {
public columns: {
id: DataType.NUMBER,
name: DataType.STRING,
age: DataType.NUMBER
}
}
const user = new User.get("id", "name")
ts.typeof user === { id: number, name: string }
**编辑#1:**作为补充,在现实中,我可以很容易地得到这样的结果:
function convert<T extends Record<string, DataType>>(schema: T) {
return {} as ConvertedType = { [K in keyof T]: T[K] extends DataType.NUMBER ? number : T[K] extends DataType.STRING ? string : never };
}
虽然它工作正常,但在更复杂的代码中却无法工作,例如:
interface Schema {
[k: string]: DataType
}
type SchemaReturn<S extends Schema, C extends keyof S> = {
[K in C]: S[K] extends DataType.NUMBER ? number : S[K] extends DataType.STRING ? string : never;
};
abstract class Model {
public schema: Schema = {};
public select<C extends keyof this["schema"]>(... columns: C[]) {
return {} as SchemaReturn<typeof this["schema"], C>;
}
}
class User extends Model {
public schema = {
id: DataType.NUMBER,
name: DataType.STRING,
age: DataType.NUMBER
}
}
const user = new User;
const data = user.select("id", "name");
data.id; // Must be `number` but got `never`
data.name; // Must be `string` but got `never`
1条答案
按热度按时间o4tp2gmn1#
我得到的结果非常接近我想要的结果,尽管用
const
替换了enum
,并且在schema
属性的类型中产生了某种“奇怪”:我愿意接受新的建议,因为我想继续使用
enum
而不是JSconst
。