为什么TypeScript不能根据参数确定返回类型?

cedebl8k  于 7个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(108)

我有一个函数,它在指定编码时返回一个字符串。否则它返回一个Buffer

import { createHash } from "crypto";

// returns a string when encoding is specified; otherwise it returns Buffer
const sha256 = (data: string | string[], encoding?: BinaryToTextEncoding) => {
  const hash = createHash("sha256");
  if (Array.isArray(data)) {
    data.forEach((s) => hash.update(s));
  } else {
    hash.update(data);
  }
  if (encoding) {
    // return string
    return hash.digest(encoding);
  }
  // return Buffer
  return hash.digest();
};

// why hashed is not string but string | Buffer
const hashed = sha256(["a", "b"], "hex");

字符串
在最后一行,我希望hashed是一个字符串,因为我已经传入了编码hex。然而,TypeScript仍然将hashed视为string | Buffer
使用@apokryfos指出的函数重载解决了这个问题

function sha256(data: string, encoding: BinaryToTextEncoding): string;

// eslint-disable-next-line no-redeclare
function sha256(data: string[], encoding: BinaryToTextEncoding): string;

// eslint-disable-next-line no-redeclare
function sha256(data: string[]): Buffer;

// eslint-disable-next-line no-redeclare
function sha256(data: string): Buffer;

// eslint-disable-next-line no-redeclare
function sha256(data: string | string[], encoding?: BinaryToTextEncoding) {
  // the same function implementation as shown above ...
}


备注:

  • 我必须禁用ESLint的规则no-redeclare
  • 我必须使用函数声明而不是箭头函数重新声明函数
kt06eoxx

kt06eoxx1#

这是函数重载的典型用例

function sha256(data: string | string[], encoding: string): Buffer;
function sha256(data: string | string[]): string;
function sha256(data: string | string[], encoding?: string): string|Buffer {
      if (encoding) {
            return Buffer.from('abc');
      }
      return 'abc';
};

const hashed = sha256(["a", "b"], "hex");
      // ^?  Buffer

const hashed2 = sha256(["a", "b"]);
      // ^? string

字符串
注意事项:虽然你注意到你需要禁用no-redeclare规则是正确的,但是该页面顶部的红色通知似乎表明你不应该在TypeScript中使用此规则。作为一个额外的旁白,使用这种方法确实需要你使用function而不是paddas。
Playground链接
还有一种实现重载的替代方法,但(出于某种原因)需要更多的转换才能工作,但是允许您使用Lambdas并且不会违反no-redeclare规则,如果这些是严格的要求:

interface Sha256 {
    (data: string | string[], encoding: string): Buffer;
    (data: string | string[]): string;
}

const sha256: Sha256 = (data: string | string[], encoding?: string) => {
    if (encoding) {
        return {} as any;
    }
    return 'abc' as any;
}

const res1 = sha256('a');
      //^? string
const res2= sha256('a','b');
      //^? Buffer


Playground链接

相关问题