我正在尝试使用advanced types编写一个函数,该函数在给定类型及其任意两个键的情况下,必须返回由两个键确定的子类型的实例。例如:
class MyClass {
id: string
name: string
age: number
}
const x = subtype(MyClass, 'id', 'name')
// x type should be { id: string, name: string }
function subtype<Class, Key1 extends keyof Class, Key2 extends keyof
Class>(
constructor: {new(): Class},
key1: Key1,
key2?: Key2,
): Pick<Class, Key1 | Key2> {
const instance = new constructor()
if (!key2) {
return pick<Class, Key1 | Key2>(instance, key1)
} else {
return pick<Class, Key1 | Key2>(instance, key1, key2)
}
}
// the function above is my current implementation, not working
问题是,因为'key2'参数是可选的,typescript无法使用Pick映射类型正确地确定类型,结果是x具有原始类的所有属性,如下所示:
const x = builder(MyClass, 'id', 'name')
// x type is { id: string, name: string, age: number } (Wrong!)
拜托,有人可以给我一个帮助吗?我真的需要保持key1和key2彼此独立,我还需要key2是可选的,所以做的事情如下:
function builder<Class, Key extends keyof Class>(
constructor: {new(): Class},
keys: Key[],
): Pick<Class, Keys> { ... }
不是我的选择。
答案 0 :(得分:0)
对于你的第一个函数,问题是如果你不提供type参数,它将被推断为最大类型(在这种情况下是T
的任何键),所以Pick
将最终包含所有属性。您可以提供带有和不带可选参数的多个签名:
function subtype<Class, Key1 extends keyof Class>(constructor: {new(): Class},key1: Key1): Pick<Class, Key1>
function subtype<Class, Key1 extends keyof Class, Key2 extends keyof Class>
(constructor: {new(): Class},key1: Key1,key2: Key2): Pick<Class, Key1 | Key2>
function subtype<Class, Key1 extends keyof Class, Key2 extends keyof Class>
(constructor: {new(): Class},key1: Key1,key2?: Key2): Pick<Class, Key1 | Key2> {
const instance = new constructor()
if (!key2) {
return pick<Class, Key1 | Key2>(instance, key1)
} else {
return pick<Class, Key1 | Key2>(instance, key1, key2)
}
}
const x = subtype(MyClass, 'id', 'name') // will have only id and name
const x2 = subtype(MyClass, 'id') // will have just id
至于第二个例子,它在语法上是不正确的,你有一个数组参数,你不用数组调用。您可以使用其余的parmaters,它会正确推断:
function builder<Class, Key extends keyof Class>(
constructor: {new(): Class},
...keys: Key[],
): Pick<Class, Key> { return null; }
const xw = builder(MyClass, 'id', 'name') // will have only id and name