为什么在只能返回窄型的映射之后,TypeScript不缩小型?

In the code below I would expect the find function to return undefined | BufferEncoding, the same type as the Map has. But undefined | string is returned. How come?

  const chartdetToFsEncodings = new Map<string, BufferEncoding>([
    ["UTF-8", "utf8"],
    ["UTF-16LE", "utf16le"],
  ]);

  const supportedEncoding = analyse(buffer)
    .map((match) => match.name)
    .find((name) =>
      chartdetToFsEncodings.get(name)
    ) as BufferEncoding;

我尝试将Map设置为const,但是出现了一些语法错误。

  const chartdetToFsEncodings = new Map<string, BufferEncoding>([
    ["UTF-8", "utf8"],
    ["UTF-16LE", "utf16le"],
  ]) as const;
评论
  • bmagni
    bmagni 回复

    find method is used by an string[], so it will return string | undefined. If you want to have BufferEncoding | undefined, this is the easiest way:

    const supportedEncoding = analyse(buffer)
        .map((match) => match.name)
        .find((name): name is BufferEncoding =>
          chartdetToFsEncodings.get(name) !== undefined
        );
    
  • 零零柒
    零零柒 回复

    The issue boils down to the incorrect use of Array.prototype.find. The method acts like a filter, but returns only the first element in the array for which the predicate returns true. In that case, it can either return an element from the mapped array, from .map(match => match.name), which is typed as string, or undefined.

    If you want to get an array of BufferEncoding instead, you can do it directly in .map() callback:

    const supportedEncoding = analyse(buffer)
        .map((match) => chartdetToFsEncodings.get(match.name))