gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 16:50:46 30 4
gpt4 key购买 nike

我刚刚创建了一个复杂的函数,它有 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];
};
}

感谢 typescript 引擎,最后一个参数(方法)的返回类型是从第二个参数(类型)中的项目推断出来的,并且 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 Code 或 Codesandbox 上使用 addMethod 函数时,第三个参数的返回类型是众所周知的,但在 monaco-editor 上不是:

Visual Studio Code enter image description here

codesandbox 编辑器 enter image description here

(失败) Monaco Editor enter image description here

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 库自动完成?

最佳答案

长话短说

在 Monaco Editor 实现正确的解决方案之前,只需使用 monaco.languages.typescript.typescriptDefaults.addExtraLib(YOUR_CUSTOM_LIBRARY,"defaultLib:lib.es6.d.ts") 并且不要理会setCompilerOptions 完全没有。您可以通过组合您想要的部分来创建自己的自定义库 https://github.com/microsoft/TypeScript/tree/master/lib .

长版

我也在使用 Monaco Editor ,但遇到了同样的问题。在仔细查看了 monaco 源代码之后,我想我找到了一个不需要修改 monaco 编辑器源代码的解决方案(解决方法?)。

首先,让我们看一下当前的行为。 Monaco Editor 使用所谓的 LanguageServiceHost实现与 TypeScript 相关的功能,另请参阅 Using the Language Service API :

It [the language host] abstracts all interactions between the language service and the external world. The language service host defers managing, monitoring and maintaining input files to the host.

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

现在,如果我们看一下源代码,我们会发现只有 two library filescurrently supported Monaco Editor :

lib.d.tscompiler option 时使用target设置为 ES5 ,否则使用 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 之类的 bundler ,我们可以将该文件替换为我们自己的版本,该版本导出常量 lib_dtslib_es6_dts 以及我们要使用的库。这个选项可能并不总是可行的,而且修改库的源代码无论如何都不是一个好主意。

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

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

总而言之,这是一个可以在 Monaco Editor playground 上运行的代码示例.请注意,这会将目标设置为 ES5(如您的示例所示),但我们也可以根本不修改编译器选项,而只使用 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

关于typescript - vscode 和 monaco-editor 之间不同的 Typescript 推理管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58834378/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com