A problem with TypeScript syndication newspaper expressions

Using TypeScript associative types at work today results in an “expression error” error because the error occurs in the reduce method of an array using reduce.

Problem description

Both the course interface and the exam interface have a status code, which respectively mark whether the course or exam is completed. Now I need to calculate the completion progress of their course and exam. Since their code logic is the same, except for the array and state fields passed in, I chose to write a function to reuse them.

The following code

interface Course{
  courseStatus:boolean
}

interface Exam{
  examStatus:boolean
}

const getCount = (isCourse: boolean) = > {
  const feild = isCourse?'courseStatus':'examStatus'
  return (list: Course[] | Exam[]) = > {
    return list.reduce((total,curr) = > {
      return total+(curr[feild]?1:0)},0)}}const getCourseCount = getCount(true)
const getExamCount = getCount(false)
Copy the code

However, an error occurs at this time.

This is why, the error indicates that my list.reduce expression is wrong.

To solve the process

I checked that my list was an array, and the array must have reduce. Why the expression was wrong? I did not report any error after I removed one type from the above joint type. But also know why, so crazy documents, fruitless, to touch the fish to ask the big guys.

The big guy saw at a glance that it was a joint type of problem, but also corrected my writing, should be changed

// This block of code is written correctly
interface Course{
  courseStatus:boolean
}

interface Exam{
  examStatus:boolean
}

const getCount = (isCourse: boolean) = > {
  const feild = isCourse?'courseStatus':'examStatus'
  return (list: (Course | Exam)[]) = > {
  //return (list: Course[] | Exam[]) => {
    return list.reduce((total,curr) = > {
      return total+(curr[feild]?1:0)},0)}}Copy the code

Why is that?

If is “course [] | Exam []” for parameter types, methods in course [] and Exam [] as the parameter type, respectively, run the function again, but when the course didn’t examStatus [] type as a parameter to this parameter, so an error, and vice versa. If you don’t understand, look directly at the following code.

interface Course{
  courseStatus:boolean
}

interface Exam{
  examStatus:boolean
}
//ts syntax check
// use Course[] as a type check
const getCount = (isCourse: boolean) = > {
  const feild = isCourse?'courseStatus':'examStatus'
  return (list: Course[]) = > {
    return list.reduce((total,curr) = > {
      // The value of feild is either courseStatus or examStatus. ExamStatus = feild; examStatus = feild; examStatus = feild;
      return total+(curr[feild]?1:0)},0)}}Exam[]
const getCount = (isCourse: boolean) = > {
  const feild = isCourse?'courseStatus':'examStatus'
  return (list: Exam[]) = > {
    return list.reduce((total,curr) = > {
      CourseStatus feild: courseStatus feild: courseStatus feild: courseStatus feild: courseStatus
      return total+(curr[feild]?1:0)},0)}}Copy the code

Therefore, when the interface has the same attribute, it can also avoid the above error, slightly change the interface attribute name and remove the useless part of the method, and get:

interface Course{
  status:boolean
}

interface Exam{
  status:boolean
}

const getCount = (list: Course[] | Exam[]) = > {
  return list.reduce((total,curr) = > {
      return total+(curr.status?1:0)},0)}Copy the code

In this case, no error will be reported, because both Course[] and Exam[] have the field name Status.

If it is “(course | Exam) []” for the parameter type, code detection may be regarded as the two interface synthesis of a new interface.

interface Course{
  courseStatus:boolean
}

interface Exam{
  examStatus:boolean
}
/ syntax check * * * * * ts to (Course | Exam) [] as type check it again, (Course | Exam) is equivalent to two interface fellowship together, form a new interface, that is: * Interface newType{* courseStatus: Boolean * examStatus: Boolean *} * So if you have both courseStatus and examStatus attributes under the new interface, no error will be reported. * /

const getCount = (isCourse: boolean) = > {
  const feild = isCourse?'courseStatus':'examStatus'
  return (list: (Course|Exam)[]) = > {
    return list.reduce((total,curr) = > {
      return total+(curr[feild]?1:0)},0)}}Copy the code

conclusion

As my experience level is limited, it is inevitable that there will be mistakes, which welcome correction.