vscode和monaco-editor之间不同的Typescript推理管理

我刚刚做了一个复杂的函数,它带有3个参数:名称,类型和方法。 此功能将方法存储在商店中。它从第二个参数推断出第三个参数的返回类型。

addMethod.d.ts

interface SimplifiedTypeMap {
  string: string;
  number: number;
  boolean: boolean;
}

type GlobalMethodAdd = <T extends keyof SimplifiedTypeMap>(
  name: string,types: T[],method: () => SimplifiedTypeMap[T]
) => void;

interface MethodStore {
  [name: string]: {
    types: (keyof SimplifiedTypeMap)[];
    method: () => SimplifiedTypeMap[keyof SimplifiedTypeMap];
  };
}

借助打字机引擎,从第二个参数(类型)中的项推断出最后一个参数(方法)的返回类型,并且int强制函数的用户编写具有特定返回类型的方法

addMethod.ts

import { random } from "lodash-es";

export const methodStorage: MethodStore = {};

const addMethod: GlobalMethodAdd = (name,types,method) => {
  methodStorage[name] = { types,method };
};

addMethod("test",["string","number"],() =>
  random(1,true) > 0.5 ? "abcd" : 1234
);

当我在Visual Studio Studio或Codesandbox上使用addMethod函数时,第三个参数的返回类型是众所周知的,但在monaco-editor上却不是这样:

Visual Studio代码

vscode和monaco-editor之间不同的Typescript推理管理

代码和框编辑器

vscode和monaco-editor之间不同的Typescript推理管理

(失败)摩纳哥编辑

vscode和monaco-editor之间不同的Typescript推理管理

Here is my example in codesandbox

================================================ ========================

编辑 我发现正是使用noLib编译器选项才能实现这一目标。

reactMonaco.languages.typescript.typescriptDefaults.setCompilerOptions({
  target: reactMonaco.languages.typescript.ScriptTarget.ES5,noLib: true,allowNonTsExtensions: true,checkJs: true,});

有没有一种方法可以避免es5 libs自动补全,同时保持推理正常进行?

lms886 回答:vscode和monaco-editor之间不同的Typescript推理管理

TL; DR

直到摩纳哥编辑器实施适当的解决方案,才使用monaco.languages.typescript.typescriptDefaults.addExtraLib(YOUR_CUSTOM_LIBRARY,"defaultLib:lib.es6.d.ts"),而完全不用理会setCompilerOptions。您可以通过组合https://github.com/microsoft/TypeScript/tree/master/lib中所需的部分来创建自己的自定义库。

长版

我也在使用monaco编辑器,并且遇到了同样的问题。在仔细研究了摩纳哥的源代码之后,我想我找到了一个不需要修改摩纳哥编辑器源代码的解决方案(解决方法?)。

首先,让我们看一下当前行为。摩纳哥编辑器使用所谓的LanguageServiceHost来实现与TypeScript相关的功能,另请参见Using the Language Service API

  

它(语言宿主)抽象了语言服务与外部世界之间的所有交互。语言服务主机推迟了对主机的输入文件的管理,监视和维护。

摩纳哥编辑器的TypeScript语言宿主是microsoft/monaco-typescript存储库的一部分,可以在tsWorker.ts中找到。

现在,如果我们看一下源代码,就会发现摩纳哥编辑器中只有two library filescurrently supported

compiler option target设置为ES5时使用

lib.d.ts,否则使用lib.es6.d.ts。更多的调试表明,无论我们为lib选项设置了什么,这两个文件之一都用作库。正如您提到的,我们可以使用noLib选项,但这会导致其他副作用,例如类型推断不再正常工作。


因此,现在我有了一个主意,在大多数情况下,您不想要没有库,而是想要一个不同的库。特定于DOM的部分(我想您不希望看到的部分)位于lib.dom.d.ts中的lib.d.ts中。 通常,最好添加至少lib.es5.d.ts,其中包含JavaScript基础类型,例如ObjectFunctionNumber;或者lib.es2015.d.ts,其中包含Symbol,新的数组方法等。因此,问题就变成了:我们如何使Monaco Editor使用自定义(可能为空)库?

monaco-typescript中,库源代码硬编码在文件lib.ts中。因此,如果使用的是诸如webpack之类的捆绑程序,则可以使用我们自己的版本替换该文件,该版本会使用我们要使用的库导出常量lib_dtslib_es6_dts。此选项可能并非总是可行,并且修改库的源代码也不是一个好主意。

但是,如果我们再看一下tsWorker.tshow it retrieves the content for a given file name,则会出现另一种解决方案(解决方法?):如果我们add an extra lib使用特定名称,则将使用额外的lib内置库。

  • 对于lib.d.ts,使用文件名defaultLib:lib.d.ts
  • 对于lib.es6.d.ts,使用文件名defaultLib:lib.es6.d.ts

总而言之,这是您的代码示例,可以在Monaco Editor playground上运行。请注意,这会将目标设置为ES5(如您的示例),但是我们也无法完全修改编译器选项,而在添加额外的lib时仅使用lib.es6.d.ts

const code = `
interface SimplifiedTypeMap {
    string: string;
    number: number;
    boolean: boolean;
}

type GlobalMethodAdd = <T extends keyof SimplifiedTypeMap>(
    name: string,types: T[],method: () => SimplifiedTypeMap[T]
) => void;

interface MethodStore {
    [name: string]: {
        types: (keyof SimplifiedTypeMap)[];
        method: () => SimplifiedTypeMap[keyof SimplifiedTypeMap];
    };
}

export const methodStorage: MethodStore = {};

const addMethod: GlobalMethodAdd = (name,types,method) => {
    methodStorage[name] = { types,method };
};

// Try hovering over addMethod,type inferrence works correctly
addMethod("test",["string","number"],() =>
    1 > 0.5 ? "abcd" : 1234
);

// No DOM library loaded,so this gives an error
new HTMLAnchorElement();    
`;

async function setup() {
    const response = await fetch("https://raw.githubusercontent.com/microsoft/TypeScript/master/lib/lib.es5.d.ts");
    const libes5 = await response.text();

    monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
        allowNonTsExtensions: true,target: monaco.languages.typescript.ScriptTarget.ES5,});

    // Use "lib.custom.d.ts" for ES5,and "defaultLib:lib.es6.d.ts" for ESNext (the default)
    monaco.languages.typescript.typescriptDefaults.addExtraLib(
        libes5,"defaultLib:lib.d.ts"
    );

    monaco.editor.create(document.getElementById("container"),{
        value: code,language: "typescript"
    });
}

setup();

另外,这里还有一个modified version of your Code Sandbox example

enter image description here

本文链接:https://www.f2er.com/3111230.html

大家都在问