推断数组中的类型

时间:2019-03-25 15:15:16

标签: typescript

给出以下内容:

class EnhancedTable extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      userID: null
    };
    this.deleteUserById = this.deleteUserById.bind(this);
  }

  componentDidMount() {
    API.post("user/all", [], config).then(({ data }) => {
      this.setState({
        data: data.response.data.map(user => (user.id, user.name, user.email))
      });
    });
  }

  deleteUserById(n) {
    console.log("user id", n);
  }

  render() {
    return (
      <TableBody>
        {data.map(n => {
          return (
            <>
              <TableCell>{n.name}</TableCell>
              <TableCell>{n.email}</TableCell>
              <TableCell>
                <DeleteIcon
                  onClick={this.deleteUserById(n.id)}
                  className="action"
                />
              </TableCell>
            </>
          );
        })}
      </TableBody>
    );
  }
}

我的类型type ArrayInfer<A> = A extends (infer I)[] ? I : never; const a = ["foo", 1, {a: "foo"}]; type inferred = ArrayInfer<typeof a>; 解析为:

inferred

但是如果我稍微更改数组以包括一个空的对象常量:

type inferred = string | number | {
    a: string;
}

然后const a = ["foo", 1, {}]; 的类型定义中不再包含inferredstring

number

那是为什么?

2 个答案:

答案 0 :(得分:2)

似乎stringnumber都可以分配给{}playground(实际上,每种类型都可以分配给{},除了{ {1}},nullvoid)。因此,TypeScript将三种类型统一为最广泛的一种。当您遇到第一种情况时,提出的三种情况中没有一种可以使用,因此您拥有一个联合。

答案 1 :(得分:1)

要扩展@Cerberus的答案并按照@Paleo在评论中的建议,JavaScript中除Object.create(null)nullundefined以外的所有类型均以Object为顶部以下代码段显示了祖先:

const arr = [{}, 1, 'hello', (a, b) => a+b, true, null, undefined, Object.create(null)];

function getPrototypeChain(value) {
  const ancestors = [];
  let proto = value;
  while (proto) {
    proto = Object.getPrototypeOf(proto);
    if (proto) {
      ancestors.push(proto.constructor.name);
    }
  };
  return ancestors
}

arr.forEach(x => console.log(x, '->', getPrototypeChain(x).join(' -> ')));

来自TypeScript文档({@ {3}},由@jcalz在注释中建议):

  

从多个表达式进行类型推断时,这些表达式的类型将用于计算“最佳通用类型”。   [...]   最佳通用类型算法会考虑每种候选类型,并选择与所有其他候选类型兼容的类型。

因此,如果您使用非空对象,则列表中将找不到最佳的通用类型,并且自

  

找不到最佳通用类型时,得出的推论是联合数组类型

结果是所有项目类型的并集。

但是,从您在列表中包含一个空对象开始,到您没有nullundefined项目的那一刻,Object便成为了最佳的通用类型和输出将是一个空对象。