You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native与Android交互时StudentInfo类型不匹配问题求助

问题:React Native遍历studentList时元素为JSON字符串,TypeScript类型不匹配报错

问题详情

遍历从Android原生传递的studentList时,每个元素实际是JSON字符串,必须通过JSON.parse才能提取字段,但TypeScript报TS2345错误:"StudentInfo类型的参数无法赋值给string类型参数"。直接解构student会导致name和course为undefined。

相关代码

StudentsScreen.tsx

export default function StudentsScreen(props: StudentInfoProps) {
  const {studentList} = props;
  console.log(typeof studentList);//object
  console.log(JSON.stringify(studentList)); //["{\"name\":\"John Doe\",\"course\":\"Javascript\"}","{\"name\":\"Jane Doe\",\"course\":\"Typescript\"}","{\"name\":\"Greg Doe\",\"course\":\"ReactNative\"}"]
  return <> {
    studentList?.map(student => {
    console.log(typeof student);//string
    const {name, course} = JSON.parse(student); //I should not need to do this
    //const {name, course} = student; //This should be enough. However, this would cause to get undefined for name and course.
    return (
      <Student
        key={uuidv4()}
        name={name}
        course={course}
      />
    );  
  })}
  </>;
}

错误信息

Screens/Students.tsx:11:53 - error TS2345: Argument of type 'StudentInfo' is not assignable to parameter of type 'string'.

11     const {name, course} = JSON.parse(student);

StudentInfo.tsx

export type StudentInfo = {
  name: string;
  course: string;
};

export type StudentInfoProps = {
  studentList: StudentInfo[];
};

export type RootStackParamList = {
  ReactNative: {studentList: StudentInfoProps};
};

Android端代码(MyReactActivity.java)

public class MyReactActivity extends ReactActivity  implements DefaultHardwareBackBtnHandler {
    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        Gson gson = new Gson();
        Bundle initialProperties = new Bundle();
            Student stud1 = new Student("John Doe", "Javascript");
            Student stud2 = new Student("Jane Doe", "Typescript" );
            Student stud3 = new Student("Greg Doe", "React Native");
            ArrayList<String> studentList = new ArrayList<>();
            studentList.add(gson.toJson(stud1));
            studentList.add(gson.toJson(stud2));
            studentList.add(gson.toJson(stud3));
            initialProperties.putStringArrayList("studentList", studentList);
            
        mReactRootView.startReactApplication(mReactInstanceManager, "RNProject", initialProperties);
        
        setContentView(mReactRootView);
    }
}

Student.java

package com.rnproject.screens.reactnative.helpers;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private String course;

    public Student(){}

    @Override
    public String toString(){
        return "{name="+name+",course="+course+"}";
    }

    public Student(String name, String course){
        this.name = name;
        this.course = course;
    }
}

期望行为

希望能像以下示例一样直接解构对象:

const students = [{"name":"John Doe",
               "course":"Typescript"},
               {"name":"Jane Doe",
               "course":"Javascript"}]


const tmp = students.map(student => {
  const {name, course} = student;
  console.log(name);
  console.log(course);
})

原因分析

Android端将每个Student对象单独序列化为JSON字符串,存入ArrayList<String>后传递给RN,导致RN接收到的是字符串数组,而非对象数组。但TypeScript类型定义中studentList被声明为StudentInfo[](对象数组),两者类型不匹配,因此出现报错。

解决方案

方案1:修改Android端代码,传递对象数组的JSON字符串

将整个学生列表序列化为单个JSON字符串,而非每个对象单独序列化:

// 替换原有的ArrayList<String>相关代码
List<Student> studentList = new ArrayList<>();
studentList.add(stud1);
studentList.add(stud2);
studentList.add(stud3);
// 将整个列表转为JSON字符串
String studentListJson = gson.toJson(studentList);
initialProperties.putString("studentList", studentListJson);

然后在RN端修改代码,先解析整个字符串为对象数组:

export default function StudentsScreen(props: { studentList: string }) {
  const { studentList } = props;
  // 解析JSON字符串为StudentInfo数组
  const students: StudentInfo[] = JSON.parse(studentList);
  
  return <> {
    students?.map(student => {
      const {name, course} = student;
      return (
        <Student
          key={uuidv4()}
          name={name}
          course={course}
        />
      );  
    })}
  </>;
}

同时更新StudentInfoProps类型定义:

export type StudentInfoProps = {
  studentList: string;
};

方案2:临时兼容现有数据格式,修正TypeScript类型

如果无法修改Android端代码,可临时修正TypeScript类型,明确studentList是字符串数组,再逐个解析:

// 修改StudentInfoProps类型
export type StudentInfoProps = {
  studentList: string[];
};

// 在组件中使用
export default function StudentsScreen(props: StudentInfoProps) {
  const {studentList} = props;
  
  return <> {
    studentList?.map(student => {
      // 类型断言确保TypeScript识别解析后的类型
      const {name, course} = JSON.parse(student) as StudentInfo;
      return (
        <Student
          key={uuidv4()}
          name={name}
          course={course}
        />
      );  
    })}
  </>;
}

总结

方案1是更规范的做法,通过传递整个数组的JSON字符串,让RN直接解析为对象数组,避免逐个解析的麻烦;方案2是临时兼容方案,适合无法修改原生代码的场景。

内容的提问来源于stack exchange,提问作者JarochoEngineer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:53:12