首页 > 解决方案 > 递归类型在发出声明后变为any,需要隐式解决方案

问题描述

我正在创建一个 npm 包,基本上它是一个返回对象的函数,该对象返回函数本身的返回值

export const chainCreator = () => {
    return {
        chain: () => {
            return chainCreator()
        },
        end: () => {
            return 'end'
        },
    }
}

在此处输入图像描述

到目前为止这么好,类型还可以

但是当我构建它时事情就坏了: 在此处输入图像描述

它返回any类型,所以这是一个很大的不

有一个解决方案,通过显式输入(类型注释)

type chainCreator = {
    (): { chain: () => ReturnType<chainCreator>; end: () => string }
}
export const chainCreator: chainCreator = () => {
    return {
        chain: () => {
            return chainCreator()
        },
        end: () => {
            return 'end'
        },
    }
}

在此处输入图像描述 这可以按预期工作,但是,我更喜欢隐式解决方案(类型推断),因为它更自动化,需要更少的维护并且更准确。

这是我的配置

{
    "compilerOptions": {
        "isolatedModules": true,
        "module": "commonjs",
        "declaration": true,
        "esModuleInterop": true,
        "sourceMap": true,
        "noImplicitAny": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "target": "esNext",
        "allowJs": true,
        "baseUrl": "src",
        "emitDeclarationOnly": true,
        "outDir": "dist",
        "paths": {
            "*": ["*"]
        },
        "typeRoots": ["./node_modules/@types"]
    },
    "include": ["src/**/*"]
}

所以我的问题是,这样的递归函数有什么隐式解决方案吗?

标签: typescript

解决方案


不,TypeScript 目前没有办法为匿名递归类型发出合理的声明文件。在microsoft/TypeScript#463中有一个非常古老的未解决问题正在讨论这个问题,虽然IntelliSense已经有了一些改进(当事情太长时你会得到那些省略号),发出到声明文件的类型仍然只是.any...any

在microsoft/TypeScript#44045有一个建议,支持在声明文件中生成自动类型别名,以便为难以扩展的匿名类型命名,因为它们非常大或递归,因此是无限的。目前尚不清楚何时或是否会实施类似的事情。给出这个问题不会有什么坏处,但它可能也无济于事。

除非有什么改变,否则你应该给匿名递归类型一个明确的名字ChainCreator,如果你需要生成准确的声明文件,你应该使用它。


推荐阅读