이 기사에서 공유한 내용은 TypeScript 변환 문제와 해결 방법에 관한 내용입니다. 다음으로 구체적인 내용을 살펴보겠습니다.
이 변환 프로젝트는 NPM을 통해 게시된 기본 서비스 패키지이므로 TypeScript를 사용하는 이 변환의 목표는 Babel 패밀리 버킷을 제거하고 패키지 크기를 줄이고 강력한 유형 제약 조건을 추가하는 것입니다. 이렇게 하면 발생할 수 있는 문제를 피할 수 있습니다. 향후 개발에서.
이 변환에서는 패키징 및 컴파일에 TypeScript v2.9.2 및 Webpack v4.16.0을 사용합니다. 개발 도구는 VSCode를 사용하고 중국어 언어 팩을 사용합니다. 예상되는 목표는 로더를 통해 TypeScript 코드를 ES5 코드로 직접 컴파일하는 것입니다.
이 기사와 관련된 문제 중 일부는 TypeScript 구성 및 사용 문제이고 일부는 VSCode 자체 구성과 관련된 문제입니다.
프로젝트에서 webpack.alias를 사용하면 모듈을 찾을 수 없다는 메시지가 나타날 수 있습니다.
구체적인 오류는 다음과 같습니다.
终端编译报错:TS2307: Cannot find module '_utils/index'. 编辑器报错:[ts]找不到模块“_utils/index”。
편집자가 해당 별칭 정보를 읽을 수 없어서 발생합니다.
이 시점에서 해당 모듈이 존재하는지 확인해야 합니다. 모듈이 존재하는 것으로 확인되고 터미널 컴파일 시 오류가 보고되지 않았으나 편집기에서는 오류만 보고되는 경우, 편집기에서 webpack 구성을 읽을 수 없기 때문에 추가 구성을 추가해야 합니다.
해결책: webpack.alias를 구성하는 것 외에도 해당 tsconfig.json
도 구성해야 합니다. 구체적인 구성은 다음과 같습니다. tsconfig.json
,具体配置如下所示:
"compilerOptions": { "baseUrl": ".", "paths": { "_util/*": [ "src/core/utils/*" ] } }
注:如果配置了tsconfig.json
以后还是报错的话,需要重启下VSCode,猜测是由于VSCode只在项目加载时读取相关配置信息。在JavaScript项目中的jsconfig.json
同理。
在JavaScript中,我们经常会声明一个空对象,然后再给这个属性进行赋值。但是这个操作放在TypeScript中是会发生报错的:
let a = {}; a.b = 1; // 终端编译报错:TS2339: Property 'b' does not exist on type '{}'. // 编辑器报错:[ts] 类型“{}”上不存在属性“b”。
这是因为TypeScript不允许增加没有声明的属性。
因此,我们有两个办法来解决这个报错:
在对象中增加属性定义(推荐)。具体方式为:let a = {b: void 0};。
这个方法能够从根本上解决当前问题,也能够避免对象被随意赋值的问题。
给a
对象增加any属性(应急)。具体方式为:let a: any = {};
。这个方法能够让TypeScript类型检查时忽略这个对象,从而编译通过不报错。这个方法适用于大量旧代码改造的情况。
与上一个情况类似,我们给一个对象中赋值一个不存在的属性,会出现编辑器和编译报错:
window.a = 1; // 终端编译报错:TS2339: Property 'a' does not exist on type 'Window'. // 编辑器报错:[ts] 类型“Window”上不存在属性“a”。
这也是因为TypeScript不允许增加没有声明的属性导致的。
由于我们没有办法声明windows属性的值(或者说很困难),因此我们需要通过下面这一种方式来解决:
我们在windows使用时增加一个类型转换,即(window as any).a = 1;
。这样就能够保证编辑器和编译时不会出错。不过该方法只建议用于旧项目改造,我们还是要尽量避免在window对象上面增加属性,应该通过一个全局的数据管理器来进行数据存取。
在项目中,使用到了一些Object原型链上面的一些ES2015新增的方法,如Object.assign
和Object.values
等,此时编译会失败,同时VSCode会提示报错:
终端编译报错:TS2339: Property 'assign' does not exist on type 'ObjectConstructor'. 编辑器报错:[ts] 类型“ObjectConstructor”上不存在属性“assign”。
这是由于我们在tsconfig.json
中指定的target
是ES5,而TypeScript并没有相关的polyfill,因此我们无法使用ES2015中新增的方法。
解决方法:可以使用lodash工具集中的相关方法,安装时需要安装lodash.assign
和@types/lodash.assign
。并且lodash.assign
是一个CMD规范的包,需要通过import _assign = require('lodash.assing');
终端编译报错:TS2693: 'Map' only refers to a type, but is being used as a value here. 编辑器报错报错:[ts] “Map”仅表示类型,但在此处却作为值使用。
tsconfig인 경우 json
이 나중에 계속 오류를 보고하면 VSCode를 다시 시작해야 합니다. VSCode는 프로젝트가 로드될 때만 관련 구성 정보를 읽는 것으로 추측됩니다. JavaScript 프로젝트의 jsconfig.json
에도 마찬가지입니다. 객체 속성 할당 오류
JavaScript에서는 빈 객체를 선언한 다음 이 속성에 값을 할당하는 경우가 많습니다. 그러나 이 작업은 TypeScript에서 오류를 발생시킵니다:🎜终端编译报错: TS2693: 'Promise' only refers to a type, but is being used as a value here. 编辑器报错:[ts] “Promise”仅表示类型,但在此处却作为值使用。
let a = {b: void 0};.
이 방법을 사용하면 현재의 문제를 근본적으로 해결하고 객체가 무작위로 할당되는 문제를 피할 수 있습니다. 🎜a
개체에 속성을 추가하세요(긴급). 구체적인 방법은 let a: any = {};
입니다. 이 방법을 사용하면 TypeScript가 유형 검사 중에 이 객체를 무시할 수 있으므로 컴파일 중에 오류가 보고되지 않습니다. 이 방법은 대량의 오래된 코드 변환에 적합합니다. 🎜"compilerOptions": { "lib": ["es2015.promise"] }
(window as any).a = 1;
입니다. 이렇게 하면 편집기와 컴파일 중에 오류가 발생하지 않습니다. 그러나 이 방법은 이전 프로젝트를 개조하는 경우에만 권장됩니다. 창 개체에 속성을 추가하는 것은 피해야 합니다. 데이터는 전역 데이터 관리자를 통해 액세스해야 합니다. 🎜Object 할당
과 같은 객체 프로토타입 체인의 일부 ES2015 새 메서드가 사용되었습니다. code> 및 Object.values
등을 사용하면 이때 컴파일이 실패하고 VSCode에서 오류 메시지가 표시됩니다. 🎜终端编译报错:TS2304: Cannot find name 'setTimeout'. 编辑器报错:[ts] 找不到名称“setTimeout”。
tsconfig.json
에 지정했기 때문입니다. > 타겟
은 ES5이고, TypeScript에는 관련 폴리필이 없으므로 ES2015에서는 새로운 메소드를 사용할 수 없습니다. 🎜🎜해결 방법: lodash 도구 세트에 있는 관련 방법을 사용할 수 있습니다. 설치 중에 lodash.sign
및 @types/lodash.sign
을 설치해야 합니다. 그리고 lodash.assing
은 CMD 표준 패키지이며 import _sign = require('lodash.assing');
을 통해 도입되어야 합니다. 🎜🎜🎜ES2015 새 데이터 구조 맵 초기화 오류 🎜🎜🎜ES2015 코드를 TypeScript 코드로 변환할 때 ES2015에서 새 맵 유형을 사용하면 편집기나 터미널 컴파일에서 컴파일할 때 오류가 보고됩니다. 🎜 "compilerOptions": { "lib": ["dom"] }
将tsconfig.json
配置中的target
属性改为es6
,即输出符合ES2015规范的代码。因为ES2015存在全局的Promise对象,因此编译和编辑器都不会报错。该方法优点为配置简单,无需改动代码,缺点为需要高级浏览器的支持或者Babel全家桶的支持。
舍弃Map类型,改用Object进行替代。这种改造比较费时费力,适用于工作量较小和不愿意引入其他文件的场景。
自行实现或者安装一个Map包。这种方法改造成本较小,缺点就是会引入额外的代码或者包,并且代码效率无法保证。例如ts-map
和typescript-map
,这两个包的查找效率都是o(n),低于原生类型的Map。因此推荐自己使用Object实现一个简单的Map,具体实现方式可以去网上找相关的Map原理分析与实践(大致原理为使用多个Object,存储不同类型元素时使用不同容器,避免类型转换问题)。
将ES2015的代码改造成为TypeScript代码时,如果你使用了ES2015的新增的Promise类型,那在编辑器还是终端编译编译时都会报错:
终端编译报错: TS2693: 'Promise' only refers to a type, but is being used as a value here. 编辑器报错:[ts] “Promise”仅表示类型,但在此处却作为值使用。
这是由于TypeScript并没有提供Promise数据类型,也没有对应的polyfill。
因此,我们解决这个问题的思路仍然有三种:
将tsconfig.json
配置文件配置中的target
属性改为es6
,即输出符合ES2015规范的代码。因为ES2015存在全局的Promise对象,因此编译和编辑器都不会报错。该方法优点为配置简单,无需改动代码,缺点为需要高级浏览器的支持或者Babel全家桶的支持。
引入一个Promise库,如bluebird等比较知名的Promise库。在安装bluebird时需要同时安装@types/bluebird声明文件。缺点就是引入的Promise库较大,而且如果你的库作为一个基础库时,可能会与其他的调用方的Promise库产生冲突。
在tsconfig.json
配置文件中增加lib。此方法的原理是让TypeScript编译时引用外部的Promise对象,因此在编译时不会报错。此方式优点是不会引入任何其他代码,但是缺点是一定要保证在引用此库的前提下,一定存在Promise对象。具体配置如下:
"compilerOptions": { "lib": ["es2015.promise"] }
将ES2015代码改造成TypeScript代码时,如果使用了setTimeout和setInterval函数时,可能会出现无法找到该函数的报错:
终端编译报错:TS2304: Cannot find name 'setTimeout'. 编辑器报错:[ts] 找不到名称“setTimeout”。
这是由于编辑器和编译时不知道当前代码运行环境导致的。
因此,我们解决这个问题的思路有两种:
在tsconfig.json
配置文件中增加lib。让TypeScript能够知道当前的代码容器。具体示例如下:
"compilerOptions": { "lib": ["dom"] }
安装@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] 应为声明或语句。
这是由于两者的模块语法不一样导致的。
因此,我们解决这个问题只需要用下面这一种方法:
将上面的export from
的语法稍加调整来适配TypeScript语法。具体改造如下:
export {default as Session} from '_models/session'; //调整后不报错 export * from '_models/read-item';// 之前不报错不需要调整
在做项目TypeScript改造的过程中,遇到了不少大大小小的坑。很多问题在网上都没有解决方案或者没有说明白具体的解决步骤,因此希望通过这一篇文章来帮助大家在进行TypeScript迁移时避免在我踩过的坑上再浪费时间。
相关推荐:
위 내용은 TypeScrip 재구성 문제 및 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!