我有一个接口Abcd
,它有几个属性:
interface Abcd {
a: string
b: number
c: boolean
d: string
}
我想为作为参数传递给函数setOptions
的对象定义一个类型Options
。在options
对象中,有两个属性:
fn
是一个异步回调,返回Abcd
的属性子集remaining
是一个包含返回类型fn
中缺少的其余属性的对象
像这样:
setOptions<Abcd>({
fn: async () => ({ a: "aaa" }),
remaining: {
b: 123,
c: false,
d: "ddd",
}
})
是否可以确保,如果fn
返回属性a
,则remaining
不应包含该属性?如果remaining
和fn
的返回值中都缺少属性,则类型也应该抱怨。它应该拒绝额外的财产。
例如:
setOptions<Abcd>({
fn: async () => ({ a: "aaa" }),
remaining: { // error, missing property `d`
a: "aaa", // error, `a` is already in the return type of `fn`
b: "bbb", // error, type of `b` should be 'number'
c: false,
e: "extra prop", // error, `e` is not in `Abcd`
}
})
我试过了:
interface Options<T extends object, U = Partial<T>, V = Omit<T, keyof U>> {
fn: () => Promise<U>
remaining: V
}
function setOptions<T extends object>(options: Options<T>) {
}
这是我最接近的尝试,但不是解决办法。
帮助:游乐场中的相同代码。
没有K
的类型推断
interface Options<T extends object, K extends keyof T> {
fn: () => Promise<Pick<T, K>>;
remaining: Omit<T, K>
}
function setOptions<T extends object, K extends keyof T>(options: Options<T, K>) {}
interface Abcd {
a: string
b: number
c: boolean
d: string
}
setOptions<Abcd, 'a'>({
fn: async () => ({ a: "aaa" }),
remaining: {
b: 123,
c: false,
d: "ddd",
}
})
具有K
的类型推断
你需要一个额外的函数调用:
const setOptions = <T extends object>() =>
<K extends keyof T>(source: {
fn: () => Promise<Pick<T, K>>;
remaining: Omit<T, K>
}) => { }
interface Abcd {
a: string
b: number
c: boolean
d: string
}
setOptions<Abcd>()({
fn: async () => ({ a: '' }),
remaining: {
b: 1,
c: false,
d: "ddd",
}
})
游乐场