为什么类型推断失败

问题描述 投票:0回答:1
  1. 我使用 ItemMap 将每种类型映射到其相应的项目。
 type ItemMap = {
  write: string[];
  see: string[];
  find: DataLibraryType[];
  read: UploadFile[];
};
  1. SearchListProps的泛型参数K用于实现不同的currentWay对应不同的列表类型。
interface SearchListProps<K extends WaysType> {
 currentWay: K;
 list: ItemMap[K];
 onClick: (val: ItemMap[K][number]) => void;
 onRemove?: () => void;
}
type WaysType = 'write' | 'read' | 'see' | 'find'

我希望列表能够根据 currentWay 的值推断出不同的类型

但是错误

参数“index”隐式具有“any”类型,但可以从使用中推断出更好的类型。 ts(7044)

并且当 currentWay = 'read' 时,列表类型错误

错误消息:类型“string | ”上不存在属性“name”数据库类型 | UploadFile”属性“name”在类型“string”上不存在。

const SearchList = <K extends WaysType>(props: SearchListProps<K>) => {
  const { currentWay, list, onClick, onRemove } = props
  switch (currentWay) {
    case 'write':
    case 'see':
    case 'find':
      return <div>
        {
          list.map((r, index) => {
            const itemName = currentWay === 'find' ? r?.name : r
            return <div key={index}>{itemName}</div>
          })
        }
      </div>
    case 'read':
      const currentFile = list?.[0]
// Attribute “name” does not exist on type “string | DataLibraryType | UploadFile<any>”  Attribute “name” does not exist on type “string”.
      const fileType = getFileExtension(currentFile?.name) || 'file'
      if (!currentFile) {
        return <></>
      }
      return <div>{currentFile?.desc}</div>
    default:
      return <></>
  }
}

我希望列表能够根据 currentWay 的值推断出不同的类型

  switch (currentWay) {
    case 'write':
    case 'see':
    case 'find':
      return <div>
        {
          list.map((r, index) => {
            const itemName = currentWay === 'find' ? r?.name : r
            return <div key={index}>{itemName}</div>
          })
        }
      </div>
    case 'read':
        // list type is UploadFile[] no error
    return <div>... </div>
    
javascript reactjs typescript
1个回答
0
投票

这里的问题是打字稿无法自行缩小 K 参数的范围。如果你想知道为什么,请参阅缩小指南,实际上相当值得一读。

所以你必须帮助 typescript 缩小范围。

首先,请在这里阅读受歧视工会

这个联合背后的想法是,如果你有一个文字类型字段,比如你的 WaysType,你可以使用联合来定义更好的类型,而不是通用的 K 类型。

type WaysType = 'write' | 'read' | 'see' | 'find';

interface BaseProps {
  onRemove?: () => void;
}

interface WriteOrSeeProps extends BaseProps {
  currentWay: 'write' | 'see';
  list: string[];
  onClick: (val: string) => void;
}

interface FindProps extends BaseProps {
  currentWay: 'find';
  list: DataLibraryType[];
  onClick: (val: DataLibraryType) => void;
}

interface ReadProps extends BaseProps {
  currentWay: 'read';
  list: UploadFile[];
  onClick: (val: UploadFile) => void;
}

type SearchListProps = WriteOrSeeProps | FindProps | ReadProps;

这里是打字稿游乐场的链接,以说明工会如何不抛出任何错误游乐场

© www.soinside.com 2019 - 2024. All rights reserved.