Maison  >  Article  >  interface Web  >  TypeScrip remodèle les problèmes et les solutions

TypeScrip remodèle les problèmes et les solutions

不言
不言original
2018-07-25 10:08:472788parcourir

Le contenu partagé avec vous dans cet article concerne les problèmes et les solutions de transformation TypeScript. Le contenu est très détaillé. Examinons ensuite le contenu spécifique, dans l'espoir d'aider tout le monde.

Vue d'ensemble

Étant donné que ce projet de transformation est un package de services de base publié via NPM, l'objectif de cette transformation utilisant TypeScript est de supprimer le bucket de la famille Babel, de réduire la taille du package , et ajoutez des contraintes de type fortes pour éviter d'éventuels problèmes lors du développement futur.

Cette transformation utilise TypeScript v2.9.2 et Webpack v4.16.0 pour le packaging et la compilation. L'outil de développement utilise VSCode et utilise le pack de langue chinoise. L'objectif attendu est de compiler directement du code TypeScript en code ES5 via le chargeur.

Certains des problèmes impliqués dans cet article sont liés à la configuration et à l'utilisation de TypeScript, et d'autres sont liés à la configuration de VSCode lui-même.

Enregistrement et analyse des problèmes de transformation

Liés au VSCode

Erreur « Impossible de trouver le module pertinent »

Dans le projet, si nous utilisons webpack.alias, nous pouvons être informés que le module est introuvable.

Les erreurs spécifiques sont les suivantes :

终端编译报错:TS2307: Cannot find module '_utils/index'.
编辑器报错:[ts]找不到模块“_utils/index”。

Cela est dû au fait que l'éditeur n'est pas en mesure de lire les informations d'alias correspondantes.

À ce stade, nous devons vérifier si le module correspondant existe. S'il est confirmé que le module existe et qu'aucune erreur n'est signalée lors de la compilation du terminal, mais que seule une erreur est signalée par l'éditeur, c'est parce que l'éditeur ne peut pas lire la configuration du webpack et que nous devons ajouter une configuration supplémentaire.

Solution : En plus de configurer webpack.alias, vous devez également configurer le tsconfig.json correspondant. La configuration spécifique est la suivante :

"compilerOptions": {
    "baseUrl": ".",
    "paths": {
        "_util/*": [
            "src/core/utils/*"
        ]
    }
}

Remarque : Si <. est configur> Si vous obtenez toujours une erreur à l'avenir, vous devez redémarrer VSCode. On suppose que VSCode ne lit les informations de configuration pertinentes que lorsque le projet est chargé. Il en va de même pour tsconfig.json dans les projets JavaScript. jsconfig.json

Lié à TypeScript

Erreur d'attribution d'attribut d'objet

En JavaScript, nous déclarons souvent un objet vide, et puis attribuez une valeur à cet attribut. Cependant, cette opération provoquera une erreur lorsqu'elle sera placée dans TypeScript :

let a = {};

a.b = 1;
// 终端编译报错:TS2339: Property 'b' does not exist on type '{}'.
// 编辑器报错:[ts] 类型“{}”上不存在属性“b”。
En effet, TypeScript ne permet pas d'ajouter des attributs non déclarés.

Par conséquent, nous avons deux façons de résoudre cette erreur :

  1. Ajouter des définitions d'attributs à l'objet (recommandé). La méthode spécifique est la suivante :

    Cette méthode peut résoudre fondamentalement le problème actuel et peut également éviter le problème des valeurs attribuées aux objets​​à volonté. let a = {b: void 0};。

  2. Ajouter n'importe quel attribut à l'objet

    (urgence). La méthode spécifique est : a. Cette méthode permet à TypeScript d'ignorer cet objet lors de la vérification du type, afin qu'aucune erreur ne soit signalée lors de la compilation. Cette méthode convient à de grandes quantités de transformations d’anciens codes. let a: any = {};

Erreur d'attribution d'attribut d'objet fenêtre signalée

Similaire à la situation précédente, lorsque nous attribuons un attribut inexistant à un objet, une modification apparaîtra Le compilateur et les erreurs signalées par le compilateur :

window.a = 1;
// 终端编译报错:TS2339: Property 'a' does not exist on type 'Window'.
// 编辑器报错:[ts] 类型“Window”上不存在属性“a”。
Cela est également dû au fait que TypeScript ne permet pas d'ajouter des attributs non déclarés.

Comme nous n'avons aucun moyen de déclarer la valeur de l'attribut windows (ou c'est très difficile), nous devons le résoudre de la manière suivante :

  1. Nous utilisation dans Windows Ajoutez une conversion de type, à savoir

    . Cela garantit qu'il n'y aura pas d'erreurs dans l'éditeur et lors de la compilation. Cependant, cette méthode n'est recommandée que pour la rénovation d'anciens projets. Nous devons essayer d'éviter d'ajouter des attributs à l'objet window. Les données doivent être accessibles via un gestionnaire de données global. (window as any).a = 1;

La nouvelle méthode ES2015 Object sur la chaîne de prototypes signale une erreur

Dans le projet, de nouvelles méthodes ES2015 sur la chaîne de prototypes Object sont utilisées Méthodes ajoutées, telles que

et Object.assign, etc., la compilation échouera à ce moment-là et VSCode affichera une erreur : Object.values

终端编译报错:TS2339: Property 'assign' does not exist on type 'ObjectConstructor'.
编辑器报错:[ts] 类型“ObjectConstructor”上不存在属性“assign”。
C'est parce que le

que nous avons spécifié dans tsconfig.json est ES5 et TypeScript n'a pas de polyfills associés, nous ne pouvons donc pas utiliser les nouvelles méthodes dans ES2015. target

Solution : vous pouvez utiliser les méthodes appropriées dans l'ensemble d'outils lodash. Vous devez installer

et lodash.assign lors de l'installation. Et @types/lodash.assign est un package standard CMD et doit être introduit via lodash.assign. import _assign = require('lodash.assing');

Nouvelle structure de données ES2015 Erreur d'initialisation de la carte

Lors de la transformation du code ES2015 en code TypeScript, si vous utilisez le nouveau type Map dans ES2015, alors une erreur sera signalée lorsque compilation dans l'éditeur ou le terminal :

终端编译报错:TS2693: 'Map' only refers to a type, but is being used as a value here.
编辑器报错报错:[ts] “Map”仅表示类型,但在此处却作为值使用。
En effet, TypeScript ne fournit pas de types de données pertinents et il n'y a pas de polyfill correspondant.

Nous avons donc trois idées pour résoudre ce problème :

  1. tsconfig.json配置中的target属性改为es6,即输出符合ES2015规范的代码。因为ES2015存在全局的Promise对象,因此编译和编辑器都不会报错。该方法优点为配置简单,无需改动代码,缺点为需要高级浏览器的支持或者Babel全家桶的支持。

  2. 舍弃Map类型,改用Object进行替代。这种改造比较费时费力,适用于工作量较小和不愿意引入其他文件的场景。

  3. 自行实现或者安装一个Map包。这种方法改造成本较小,缺点就是会引入额外的代码或者包,并且代码效率无法保证。例如ts-maptypescript-map,这两个包的查找效率都是o(n),低于原生类型的Map。因此推荐自己使用Object实现一个简单的Map,具体实现方式可以去网上找相关的Map原理分析与实践(大致原理为使用多个Object,存储不同类型元素时使用不同容器,避免类型转换问题)。

ES2015新增的Promise使用报错

将ES2015的代码改造成为TypeScript代码时,如果你使用了ES2015的新增的Promise类型,那在编辑器还是终端编译编译时都会报错:

终端编译报错: TS2693: 'Promise' only refers to a type, but is being used as a value here.
编辑器报错:[ts] “Promise”仅表示类型,但在此处却作为值使用。

这是由于TypeScript并没有提供Promise数据类型,也没有对应的polyfill。

因此,我们解决这个问题的思路仍然有三种:

  1. tsconfig.json配置文件配置中的target属性改为es6,即输出符合ES2015规范的代码。因为ES2015存在全局的Promise对象,因此编译和编辑器都不会报错。该方法优点为配置简单,无需改动代码,缺点为需要高级浏览器的支持或者Babel全家桶的支持。

  2. 引入一个Promise库,如bluebird等比较知名的Promise库。在安装bluebird时需要同时安装@types/bluebird声明文件。缺点就是引入的Promise库较大,而且如果你的库作为一个基础库时,可能会与其他的调用方的Promise库产生冲突。

  3. tsconfig.json配置文件中增加lib。此方法的原理是让TypeScript编译时引用外部的Promise对象,因此在编译时不会报错。此方式优点是不会引入任何其他代码,但是缺点是一定要保证在引用此库的前提下,一定存在Promise对象。具体配置如下:

    "compilerOptions": {
        "lib": ["es2015.promise"]
    }

SetTimeout使用报错

将ES2015代码改造成TypeScript代码时,如果使用了setTimeout和setInterval函数时,可能会出现无法找到该函数的报错:

终端编译报错:TS2304: Cannot find name 'setTimeout'.
编辑器报错:[ts] 找不到名称“setTimeout”。

这是由于编辑器和编译时不知道当前代码运行环境导致的。

因此,我们解决这个问题的思路有两种:

  1. tsconfig.json配置文件中增加lib。让TypeScript能够知道当前的代码容器。具体示例如下:

    "compilerOptions": {
        "lib": ["dom"]
    }
  2. 安装@types/node。该方法适用于node环境下或者采用webpack打包时可以引入node代码。该方法直接通过npm install @types/node即可安装完成,解决报错问题。

模块引用和导出报错

在ES2015的代码中,我们可以通过@babel/plugin-proposal-export-default-from插件来直接导出引入的文件,具体示例如下:

export Session from './session'; // 报错
export * from '_models/read-item'; // 不报错

而在TypeScript中,这种写法是会报错的:

终端编译报错:TS1128: Declaration or statement expected.
编辑器报错:[ts] 应为声明或语句。

这是由于两者的模块语法不一样导致的。

因此,我们解决这个问题只需要用下面这一种方法:

  1. 将上面的export from的语法稍加调整来适配TypeScript语法。具体改造如下:

    export {default as Session} from '_models/session'; //调整后不报错
    export * from '_models/read-item';// 之前不报错不需要调整

总结

在做项目TypeScript改造的过程中,遇到了不少大大小小的坑。很多问题在网上都没有解决方案或者没有说明白具体的解决步骤,因此希望通过这一篇文章来帮助大家在进行TypeScript迁移时避免在我踩过的坑上再浪费时间。

相关推荐:

关于TypeScript在node项目中的实践分析

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn