簡體   English   中英

為什么 Typescript 將我的 keyof 類型強制為 never 類型,我該如何解決?

[英]Why is Typescript coercing my keyof type to a never type and how do I fix it?

對不起,如果這是一個騙局,我是 TypeScript 的新手,並且無法弄清楚看起來相似的問題是否相關,因為他們中的很多人都在做非常復雜的事情。 無論如何,問題是,我有一個相對簡單的設置,TS 正在窒息,因為它強制一種類型never ,我真的不明白它為什么這樣做。 這是設置:

interface BigObject {
  foo: {
    a?: string
    b?: string
  }
  bar: {
    c?: string
    d?: string
  }
}

const instance: BigObject = {
  foo: {
    a: "a",
    b: "b",
  },
  bar: {
    c: "c",
    d: "d",
  }
}

function metafunction(bigObjProp: keyof BigObject) {
  type LittleObject = BigObject[typeof bigObjProp]
  // IDE hints show this ^^ as being correct, i.e. either of the two "sub interfaces"

  return function (littleObjProp: keyof LittleObject) { // <== littleObjProp is resolving to never
    return function (bigObject: BigObject) {
      const littleObject = bigObject[bigObjProp]
      return littleObject ? littleObject[littleObjProp] : "fallback value"
    }
  }
}

const firstClosure = metafunction("foo")
const secondClosure = firstClosure("a") // <== Argument of type "a" is not assignable to type "never"
const value = secondClosure(instance)

我的期望是 value 的value將是“a”。

我不明白為什么littleObjProp解析為never 我的假設是,由於LittleObject是從傳遞給參數的類型內置metafunction ,TS會選擇使用任何給定調用其“子接口”。 因此,例如,當我調用metafunction("foo") ,TS 會將LittleObject設置為{ a?: string; b?: string } { a?: string; b?: string }因此,當我調用firstClosure("a") ,它會說,“啊,是的,'a' 確實是 LittleObject 的有效鍵,繼續”。 然而,它不能這樣做,因為它總是認為keyof LittleObject意味着never

有人可以幫助我理解 1) 為什么這樣做和 2) 如何完成我正在嘗試做的事情? 我意識到這是一個奇怪的設置,但我正在處理一些奇怪的 React 庫,而這正是我目前所處的位置。 請假設我必須保持一個函數的整體結構,該函數返回一個返回一個函數的函數,如示例中所示。 另外,如果您能盡可能簡單地回答我的問題,我將不勝感激,因為我對 TS 有點陌生。 提前致謝!

使metafunction通用。

正如上面所說,沒有泛型類型。 為了安全起見, firstClosure只會采用foobar共有的鍵,但它們沒有共同的鍵,所以never是唯一可能的參數。 如果您要給它們一個共同的鍵, firstClosure鍵入firstClosure以接受該鍵。

interface BigObject {
  foo: {
    a?: string
    b?: string
    f?: string   // Added
  }
  bar: {
    c?: string
    d?: string
    f?: string   // Added
  }
}

const instance: BigObject = {
  foo: {
    a: "a",
    b: "b",
    f: "f",
  },
  bar: {
    c: "c",
    d: "d",
    f: "f",
  }
}

const secondClosure = firstClosure("f")   // "f" is the only valid value

打字稿游樂場

通過添加泛型,您可以說服 Typescript 將類型信息保留為metafunctionfirstClosure每個的屬性,這為您的閉包提供您正在尋找的類型。

function metafunction<T extends keyof BigObject>(bigObjProp: T) {
  type LittleObject = BigObject[T]

  return function (littleObjProp: keyof LittleObject) {
    return function (bigObject: BigObject) {
      const littleObject = bigObject[bigObjProp]
      return littleObject[littleObjProp] ?? "fallback value"
    }
  }
}

打字稿游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM