简体   繁体   English

Reactjs Typerscript:类型“ never”上不存在属性“ toLowerCase”

[英]Reactjs Typerscript: Property 'toLowerCase' does not exist on type 'never'

Im trying to filter data with multiple key value in reactjs with tsx. 我试图在带有tsx的reactjs中过滤具有多个键值的数据。 Cards.tsx is a parent component and ShipmentCard.tsx is a child. Cards.tsx是父组件,而ShipmentCard.tsx是子组件。 I'm getting Property 'toLowerCase' does not exist on type 'never' error. 我收到Property 'toLowerCase' does not exist on type 'never'错误的Property 'toLowerCase' does not exist on type 'never' I just want to return the related object based on search criteria. 我只想根据搜索条件返回相关对象。 Can anyone let me know where I made a mistake? 谁能告诉我我在哪里犯错了?

Cards.tsx Cards.tsx

 class Cards extends Component { state = { card: [], filter: "" }; componentDidMount() { this.loadShipmentList(); } handleChange = (event: any) => { this.setState({ filter: event.target.value }); }; loadShipmentList() { fetch("http://localhost:3001/shipments") .then(response => response.json()) .then(data => this.setState({ card: data })); } render() { const { card, filter } = this.state; const lowercasedFilter = filter.toLowerCase(); const filteredData = this.state.card.filter(item => { return Object.keys(item).some(key => item[key].toLowerCase().includes(lowercasedFilter) ); }); return ( <Card className="Search-Bar"> <CardContent> <Grid container spacing={3}> <TextField label="Search" onChange={this.handleChange} /> </Grid> </CardContent> </Card> <Grid container spacing={3}> {filteredData.map((card: any) => ( <Grid item xs={12}> <ShipmentCard key={card.id} value={card} /> </Grid> ))} </Grid> ); } } export default Cards; 
db.json db.json

 { "shipments": [ { "id": "123", "name": "Heromisha", "total": "1000", "status": "ACTIVE", "userId": "E222" }, { "id": "456", "name": "Honda", "total": "3000", "status": "ACTIVE", "userId": "E111" } ] } 

Component is a generic interface with two type parameters: The type of your props, and the type of your state. Component是具有两个类型参数的通用接口:道具的类型和状态的类型。 Your component doesn't seem to have props so you can just use object or {} for the props interface, but you do have state, so you need to say what shape that state has: 您的组件似乎没有道具,因此您只能将object{}用于道具接口,但是您确实有状态,因此您需要说明该状态的形状

interface Card {
  id:     string;
  name:   string;
  total:  string;
  status: string;
  userId: string;
}
interface CardsState {
  card:   Card[];
  filter: string;
}
class Cards extends Component<object,CardsState> {
  state: CardsState = {
    card: [],
    filter: ""
  };
  // ...
}

Separately, the next couple of problems I suspect you'll have are: 另外,我怀疑您接下来会遇到的两个问题是:

  1. You're not checking that fetch succeeded. 您没有检查是否成功fetch You're not alone in this, it's a very common error (so common I wrote it up on my anemic little blog). 您并不孤单,这是一个非常常见的错误(很常见,我在贫乏的小博客上写下了它 )。 You need to add a check to your fetch call: 您需要在fetch调用中添加一张支票:

     fetch("http://localhost:3001/shipments") .then(response => { if (!response.ok) { throw new Error("HTTP error " + response.status); } return response.json(); }) // ... 
  2. You're not handling errors from fetch . 您不处理来自fetch错误。 loadShipmentList should either return the promise chain (and then componentDidMount and other places it's used would handle errors) or handle/report errors itself. loadShipmentList应该返回承诺链(然后componentDidMount及其使用的其他位置将处理错误)或自身处理/报告错误。

  3. You're setting card to the result of parsing your JSON. 您正在将card设置为解析JSON的结果。 Your code assumes card is an array, but the JSON's top level isn't an array, it's an object with a shipments property (which is an array). 您的代码假设card是一个数组,但是JSON的顶层不是数组,它是一个带有shipments属性的对象(它是一个数组)。 I suspect you meant to set card (which should be cards , plural, or shipments ) to the shipments property of the returned data: 我怀疑您是想将card (应该是cards ,plural或shipments )设置为返回数据的shipments属性:

     .then(({shipments}) => this.setState({ card: shipments })); // ^^ ^^ ^^^^^^^^^ 

There may be further issues, but the main answer above should address the never issue, and hopefully these further hints have helped. 可能还有其他问题,但是上面的主要答案应该解决never问题,希望这些进一步的提示有所帮助。


In a comment you've said that when you give card a type, this code causes an error: 在评论中,您说过,当您给card指定类型时,此代码会导致错误:

const filteredData = this.state.card.filter(item => {
  return Object.keys(item).some(key =>
    item[key].toLowerCase().includes(lowercasedFilter)
  );
});

If you expect the shape of the data in the JSON to be variable, you could declare card as any[] (or perhaps Record<string,string>[] ) and then that dynamic code would work. 如果您希望JSON中的数据形状可变,则可以将card声明为any[] (或也许Record<string,string>[] ),然后该动态代码将起作用。 But only if you want the component driven by the JSON. 但仅当您希望组件由JSON驱动时。 Otherwise, update the code to use the typesafe property names: 否则,更新代码以使用typesafe属性名称:

const filteredData = this.state.card.filter(({id, name, total, status, userId}) =>
  `${id}\t${name}\t${total}\t${status}\t${userId}`.toLowerCase().includes(lowercasedFilter)
);

The compiler doesn't real type of state.card[...], becouse it's declared as array. 编译器不是state.card [...]的真实类型,因为它被声明为数组。 The most simple way is to declare this as any[] 最简单的方法是将其声明为any []

  state = {
    card: [] as any[],
    filter: ""
  };

Or describe data type explicit 或显式描述数据类型

interface Card {
    "id": string,
    "name": string,
    "total": string,
    "status": string,
    "userId": string
}
...
      state = {
        card: [] as Card[],
        filter: ""
      };

Or by object example 或通过对象示例

const cardSample = {
      "id": "123",
      "name": "Heromisha",
      "total": "1000",
      "status": "ACTIVE",
      "userId": "E222"
  };

type Card = typeof cardSample;

    ...
          state = {
            card: [] as Card[],
            filter: ""
          };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM