我的目標是 foo 接受任何擴展Obs<T>. 但是我收到以下錯誤。
Argument of type '{ reset: () => number; x: number; set: (x: number) => number; }' is not assignable to parameter of type 'Obs<unknown>'.
Object literal may only specify known properties, and 'reset' does not exist in type 'Obs<unknown>'
片段 A
{
// add a generic method ??
type Obs<T> = { x: T; set: (x: T) => T }
function createObs<T>(x: T): Obs<T> {
return { x, set: (val: T) => val }
}
function foo<O extends Obs<T>, T>(a: O) {}
const a = createObs(1)
foo({ ...a, reset: () => 1 }) // ? now throws the error
}
有趣的是,如果我洗掉該set方法,這些型別會像預期的那樣作業。
片段 B
{
type Obs<T> = { x: T }
function createObs<T>(x: T): Obs<T> {
return { x }
}
function foo<O extends Obs<T>, T>(a: O) {}
const a = createObs(1)
foo({ ...a, reset: () => 1 }) // ?
}
TS 游樂場鏈接
如何使代碼段 A 與泛型set方法一起作業?
uj5u.com熱心網友回復:
這些問題似乎與你沒有定義什么將成為默認值的事實相關聯T的foo功能。
如果您infer通過傳入的任何內容 T 默認型別Obs,打字稿將有足夠的資訊來使用您之前傳遞給createObs函式的型別。
{
type Obs<T> = { x: T; set: (x: T) => T };
function createObs<T>(x: T): Obs<T> {
return { x, set: (val: T) => val };
}
function foo<O extends Obs<T>, T = O extends Obs<infer R> ? R : never>(
a: O
) {}
const a = createObs(1);
foo({ ...a, reset: () => 1 });
}
uj5u.com熱心網友回復:
您需要添加額外的泛型引數:
// U is extra generic parameter
type Obs<T> = { x: T; set: <U extends T>(x: U) => T }
function createObs<T>(x: T): Obs<T> {
return { x, set: (val: T) => val }
}
function foo<O extends Obs<T>, T>(a: O) { }
const a = createObs(1)
a.set(2) // ok
foo({ ...a, reset: () => 1 })
操場
T在 中協變type Obs<T> = { x: T }。考慮這個例子:
type Obs<T> = { x: T }
let foo: Obs<number> = { x: 0 }
let bar: Obs<42> = { x: 42 }
foo = bar
bat可分配給foo。
但是如果你添加一個set方法,就像這里:
type Obs<T> = { x: T, set: (x: T) => T }
T 變得不變。
type Obs<T> = { x: T, set: (x: T) => T }
let foo: Obs<number> = { x: 0, set: (val) => val }
let bar: Obs<42> = { x: 42, set: (val) => val }
foo = bar // error
bar = foo // error
bar不再可分配給foo。
因此,如果你想它的作業,你需要做的論點set的一個亞型T。
老實說,我不確定T becomes invariant。所以,如果你對此有任何爭論,我愿意接受批評。
PS 更多關于 *-variance 你會在這里找到
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/349977.html
下一篇:省略從不輸入打字稿
