簡體   English   中英

Typescript 條件類型缺失屬性

[英]Typescript conditional type missing properties

我無法理解為什么以下 TypeScript 代碼會失敗,而看似一切都應該沒問題:

interface Base { basic: boolean };
interface Super { basic: boolean; extra: boolean };

type Options<T> = T extends Super ? { isSuper: boolean } : { notSuper: boolean }

const baseOptions: Options<{ basic: boolean }> = { notSuper: true };                 // ok
const superOptions: Options<{ basic: boolean; extra: boolean }> = { isSuper: true }; // ok

type MakeOptions = <T>() => Options<T>

function withOptions <T>(makeOptions: MakeOptions): void {
  const options = makeOptions<T>();

  console.log(options.notSuper); // Error: Property 'notSuper' does not exist on type 'Options<T>'.(2339)
  console.log(options.isSuper);  // Error: Property 'isSuper' does not exist on type 'Options<T>'.(2339)
}

我希望options.isSuper undefined | { isSuper: boolean } undefined | { isSuper: boolean }options.notSuper undefined | { notSuper: boolean } undefined | { notSuper: boolean }

相反,Typescript 將這些屬性全部刪除。

更改為時問題已解決

type Options<T> = T extends Super ? { isSuper: boolean; notSuper?: undefined } : { notSuper: boolean; isSuper?: undefined }

但這似乎沒有必要。

操場

Options<T>中,您希望它返回帶有參數isSupernotSuper我在他們兩個的接口中添加。

interface IisSuper { isSuper: boolean }
interface InotSuper { notSuper: boolean }

Options<T>中,因為它可以是上述接口之一,所以我為它創建了一個名為TSuper的聯合類型。

type Options<T> = T extends Super ? IisSuper : InotSuper
type TSuper = IisSuper | InotSuper

在 function withOptions<T>中,我使用了as關鍵字,這是一個類型斷言,它告訴編譯器將 object 視為另一種類型,而不是編譯器推斷 ZA8CFDE6331BD59EB2666F8911ZB4 的類型。 在這種情況下, Options<T>可以作為IisSuperInotSuper的並集存在。

由於 Typescript 無法保證運行時options的類型,因為您想訪問notSuperisSuper因此您必須使用in關鍵字縮小 scope 的options ,以訪問所需類型的參數。

function withOptions <T>(makeOptions: MakeOptions): void {
  const options = makeOptions<T>() as TSuper;
  if('notSuper' in options){
    console.log(options.notSuper);
  }
  else if('isSuper' in options){
    console.log(options.isSuper);
  } 
}

最終代碼:

interface Base { basic: boolean };
interface Super { basic: boolean; extra: boolean };
interface IisSuper { isSuper: boolean }
interface InotSuper { notSuper: boolean }

type Options<T> = T extends Super ? IisSuper : InotSuper
type MakeOptions = <T>() => Options<T>
type TSuper = IisSuper | InotSuper

const baseOptions: Options<{ basic: boolean }> = { notSuper: true };                 
const superOptions: Options<{ basic: boolean; extra: boolean }> = { isSuper: true }; 

function withOptions <T>(makeOptions: MakeOptions): void {
  const options = makeOptions<T>() as TSuper;
  if('notSuper' in options){
    console.log(options.notSuper);
  }
  else if('isSuper' in options){
    console.log(options.isSuper);
  } 
}

暫無
暫無

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

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