【问题标题】:return union type Promise<string | fs.WriteStream> not working返回联合类型 Promise<string | fs.WriteStream> 不工作
【发布时间】:2022-01-12 18:22:49
【问题描述】:

我正在尝试使 函数 返回两种可能的数据类型。它可以返回的第一种类型是string,它可以返回的第二种类型是fs.WriteStream

在函数中,这是基于您传递给它的名为stream?: boolean的参数

如图所示,VSCode 正确显示了这个函数的这种行为

但是,智能感知以某种方式仅将其识别为string,而实际类型也可能是fs.WriteStream

但是如果我强制它是 fs.WriteSteam 类型使用

const tt = await getFromUrl(s, true) as fs.WriteStream;

效果很好

这是怎么回事?如何在不强制使其成为类型的情况下使这种联合类型正常工作?


这是完整的代码,以防您不想复制它

import { existsSync, readFileSync } from 'fs'
import https from 'https'
import fs from 'fs'
import crypto from 'crypto'

/**
 * Converts given source from a SRT format to a WebVTT format
 * 
 * Srt must be one of type
 * - Path to subtitle file (only for NodeJS environments)
 * - URL to a subtitle file (for browser and NodeJS)
 * - SRT text content (for browser and NodeJS)
 * 
 * @param srt { string }
 * @returns string
 * @example
 * convert(`./path/to/subtitle.srt`) // only for nodejs
 * convert(`https://example.com/english.srt`) // works for both browser and nodejs
 * convert(`1
00:00:00,207 --> 00:00:05,520
Amerikaanse Ministerie
van Magie.

2
00:00:06,625 --> 00:00:09,034
New York, 1927

3
00:00:10,878 --> 00:00:15,547
Je zal blij zijn van hem af te zijn
neem ik aan?`) // works for both browser and nodejs
 */
export async function convert(srt: string) {
    const s = srt.trim()
    const isUri = s.startsWith("http://") || s.startsWith("https://")
    const isPath = /^([a-z]:)?([.\/]+)?((\\|\/|\\\\)?[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.srt$/i.test(s)

    if(isPath && existsSync(s)) {
        return srtToVtt(readFileSync(s, 'utf8'));
    }
    if(isUri) {
        const tt = await getFromUrl(s);

        console.log(tt.path);
    }

    // Must be the contents of an srt file of we get here
    return ''
}

/**
 * Fetches text content from srt file over web
 * 
 * @param url 
 * @param stream    - return result as a writeable stream or just the data (default true)
 */
export async function getFromUrl(srt: string, stream = true): Promise<string | fs.WriteStream> {
    return new Promise(resolve => {
        https.get(srt, response => {
            if(stream) {
                const str = fs.createWriteStream(crypto.randomBytes(16).toString("hex") + '.srt')
    
                response.pipe(str).on('finish', () => {
                    str.end().close();

                    return resolve(str)
                })
            } else {
                let srtFile = '';

                response.on("data", function(chunk) {
                    srtFile += chunk;
                });

                response.on('end', () => {
                    console.log('test')
                    return resolve(srtFile)
                })
            }
        })
    })
}

【问题讨论】:

  • don't post images of code。花时间写出最少的必要代码来说明您的问题并转录(复制粘贴)相关的错误文本。
  • @pilchard 我必须展示 VSCode 向我展示的内容。
  • @pilchard 它有它的用途,这是发布图片的完全正当理由。检查我所有的其他问题.. 我从不发布图片,但我必须向观众展示确切的问题。在这种情况下,VSCode 会向我显示错误,我不能在不添加上下文的情况下粘贴这些错误。
  • 至少发布给您带来问题的功能的相关代码。图像模糊了函数体。
  • @pilchard 我同意你的观点,我粘贴了完整的代码来复制问题

标签: javascript typescript


【解决方案1】:

为什么会出现此错误:

tt 变量的类型是string | fs.WriteStream。由于您不知道该变量中有两种类型中的哪一种,因此您想要访问的任何方法或属性都必须存在于 both 类型中。

如您所见,您可以通过将变量的类型缩小到该联合的一侧或另一侧来解决此问题。您可以通过手动转换(您的as fs.WriteStream)来做到这一点如果您使用控制流进行检查,TypeScript 可以推断出正确的类型:

if (typeof tt === "string") {
   // tt has type string in this block.
   return;
}

// tt has type fs.WriteStream from here forward.

考虑重载:

这个函数可能会从overload signature 中受益,这样就可以消除您获得联合的哪一部分的歧义。这样,TypeScript 可以根据您调用函数的方式推断出正确的返回类型。

async function getFromUrl(srt: string, stream?: false): Promise<string>;
async function getFromUrl(srt: string, stream: true): Promise<fs.WriteStream>;
async function getFromUrl(srt: string, stream?: boolean): Promise<string | fs.WriteStream> {
  return ""
}

const str1 = await getFromUrl("")         // string
const str2 = await getFromUrl("", false)  // string
const stream = await getFromUrl("", true) // fs.WriteStream

【讨论】:

  • 感谢详细解答,成功了
猜你喜欢
  • 2021-02-06
  • 1970-01-01
  • 2021-10-17
  • 2011-01-10
  • 1970-01-01
  • 2018-01-07
  • 2021-03-25
  • 1970-01-01
  • 2022-12-18
相关资源
最近更新 更多