简体   繁体   中英

Why doesn't TypeScript narrow type after a map that can only return the narrow type?

In the code below I would expect the find function to return undefined | BufferEncoding undefined | BufferEncoding , the same type as the Map has. But undefined | string 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;

I tried setting the Map as const, but got some syntax error.

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

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))

find method is used by an string[] , so it will return string | undefined string | undefined . If you want to have BufferEncoding | undefined 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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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