欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深入理解TypeScript

程序员文章站 2024-02-19 18:12:04
...

编译上下文

在一个项目中,如果想使用ts来进行开发,就需要一个相关的配置文件,tsconfig.json。

你可以在项目的根目录下手动创建这个文件,写入一些你需要的配置。

也可以使用命令生成这样的一个文件:

npm install -g typescript

以上命令会在全局环境下安装 tsc 命令,安装完成之后,我们就可以在任何地方执行 tsc 命令了。

进入你的项目,执行:

tsc --init

会在你的项目根目录下生成一个tsconfig.json文件:

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5", // 指定 ECMAScript 目标版本: 'ES3'(default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
    "module": "commonjs", /* 指定使用的模块: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    // "lib": [],                             /* 指定要包含在编译中的库文件 */
    // "allowJs": true,                       /* 允许编译 javascript 文件 */
    // "checkJs": true,                       /* 报告 javascript 文件中的错误 */
    // "jsx": "preserve",                     /* Specify JSX code generation(指定 jsx 代码的生成): 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding(生成相应的 '.d.ts' 文件) '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */ 生成相应的 '.map' 文件
    // "outFile": "./",                       /* Concatenate and emit output to single file. (将输出文件合并为一个文件) */
    // "outDir": "./",                        /* Redirect output structure to the directory.(指定输出目录) */
    // "rootDir": "./",                       /* (用来控制输出目录结构 --outDir.)Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* (删除编译后的所有的注释)Do not emit comments to output. */
    // "noEmit": true,                        /* (不生成输出文件)Do not emit outputs. */
    // "importHelpers": true,                 /* (从 tslib 导入辅助工具函数)Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
    /* Strict Type-Checking Options */
    "strict": true, /*(启用所有严格类型检查选项) Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /*(在表达式和声明上有隐含的 any类型时报错) Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* (启用严格的 null 检查)Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* (当 this 表达式值为 any 类型的时候,生成一个错误)Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* (以严格模式检查每个模块,并在每个文件里加入 'use strict')Parse in strict mode and emit "use strict" for each source file. */
    /* Additional Checks */
    // "noUnusedLocals": true,                /* (有未使用的变量时,抛出错误)Report errors on unused locals. */
    // "noUnusedParameters": true,            /* (有未使用的参数时,抛出错误)Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* (并不是所有函数里的代码都有返回值时,抛出错误)Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* (报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿))Report errors for fallthrough cases in switch statement. */
    /* Module Resolution Options(模块解析选项) */
    // "moduleResolution": "node",            /* (选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6))Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* (用于解析非相对模块名称的基目录)Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* (模块名到基于 baseUrl 的路径映射的列表)A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* (根文件夹列表,其组合内容表示项目运行时的结构内容)List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* (包含类型声明的文件列表)List of folders to include type definitions from. */
    // "types": [],                           /* ( 需要包含的类型声明文件名列表)Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* (允许从没有设置默认导出的模块中默认导入)Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
    /* Source Map Options */
    // "sourceRoot": "",                      /* (指定调试器应该找到 TypeScript 文件而不是源文件的位置)Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* (指定调试器应该找到映射文件而不是生成文件的位置)Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* (生成单个 soucemaps 文件,而不是将sourcemaps 生成不同的文件)Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* (将代码与 sourcemaps 生成到一个文件 中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性)Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
    /* Experimental Options */
    // "experimentalDecorators": true,        /* (启用装饰器) Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* (为装饰器提供元数据的支持)Enables experimental support for emitting type metadata for decorators. */
    /* Advanced Options */
    "skipLibCheck": true, /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  }
}

运行 tsc,它会在当前目录或者是父级目录寻找 tsconfig.json 文件。

创建一个index.ts文件

function sayHello(person: string) {
    return 'Hello, ' + person;
}

let user = 'Tom';
console.log(sayHello(user));

运行tsc index.ts,会生成一个编译好的index.js文件:

function sayHello(person) {
    return 'Hello, ' + person;
}
var user = 'Tom';
console.log(sayHello(user));

深入理解TypeScript

声明空间

在 TypeScript 里存在两种声明空间:类型声明空间与变量声明空间。我将会在下文中和大家讨论这 两个概念。

类型声明空间

类型声明空间包含用来当做类型注解的内容,例如以下的一些类型声明:

class Foo {}
interface Bar {} 
type Bas = {};

你可以将 Foo , Bar , Bas 做为类型注解使用,但是不能用做变量。

let foo: Foo; 
let bar: Bar; 
let bas: Bas;

深入理解TypeScript

Bar并未定义在变量声明空间。

变量声明空间

变量声明空间包含可用作变量的内容,在上文中 Class Foo 提供了一个类型 Foo空间,此外它同样提供了一个变量 Foo 到变量声明空间,如下所示:

深入理解TypeScript

一些像你用 var 声明的变量,也仅能在变量声明空间使用,不能用作类型注解。

深入理解TypeScript

模块

全局模块

 

如果把tsconfig.json文件去掉,执行tsc index.ts也可以生成index.js文件,但是回到index.ts文件中,会发现红色波浪心,大致意思就是重复声明了变量和函数。

深入理解TypeScript

这是因为,默认情况下,当你开始在一个新的 TypeScript 文件中写下代码时,它处于全局命名空间中。也就是说可以在任何文件中访问这些变量,毋庸置疑,使用全局变量空间是危险的,因为它会与文件内的代码命名冲突。我们推荐使用下文中将要 提到的文件模块。

验证一下:

先删除生成的index.js文件,新建一个bar.js文件,age会报错,但user不会:

深入理解TypeScript

文件模块

如果在你的 TypeScript 文件的根级别位置含有 import 或者export ,它会在这个文件中创建一个本地的作用域。就不会再出现上面的问题。

深入理解TypeScript

user也报错了:

深入理解TypeScript

模块引入

  • 可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加 载在这个对象上面:

bar.ts

export const foo = 123;
export function fun() {
    console.log('fun')
}

foo.ts

import * as React from './bar'

console.log(React)

执行tsc foo.ts编译出js文件,然后node foo.js

增加默认导出:

bar.ts

export const foo = 123;
export function fun() {
    console.log('fun')
}
const React = {};
export default React
tsc foo.ts

node foo.js

深入理解TypeScript

 编译后的foo.js

"use strict";
exports.__esModule = true;
var React = require("./bar");
console.log(React);

深入理解TypeScript

可以看到,所有的导出都被加在了React对象上面。

  • 你可以重命名变量导出:
// bar.ts
const someVar = 123;
export { someVar as aDifferentName };
 
  • 重命名导出变量或者类型:
// foo.ts
2. import { someVar as aDifferentName } from './bar';
  • 从其他模块导入后整体导出:
export * from './foo';
  • 从其他模块导入后,部分导出:
    
export { someVar } from './foo';

当导入路径不是相对路径时,模块解析将会模仿 Node 模块解析策略 ,以下我将给出一个简单例 子:

当你使用 import * as foo from 'foo' ,将会按如下顺序查找模块:

  • ./node_modules/foo
  • ../node_modules/foo
  • ../../node_modules/foo

直到系统的根目录
当你使用 import * as foo from 'something/foo' ,将会按照如下顺序查找内容

  • ./node_modules/something/foo
  • ../node_modules/something/foo
  • ../../node_modules/something/foo

直到系统的根目录

什么是 place?

当我提及被检查的 place 时,我想表达的是在这个 place ,TypeScript 将会检查以下内容 (例如一个 foo 的位置):

如果这个 place 表示一个文件,如: foo.ts ,欢呼!
否则,如果这个 place 是一个文件夹,并且存在一个文件 foo/index.ts ,引入的就是这个index.ts文件。

否则,如果这个 place 是一个文件夹,并且存在一个 foo/package.json 文件,在该文件 中指定 types 的文件存在,引入的就是package.json指定的type文件。.d.ts
否则,如果这个 place 是一个文件夹,并且存在一个 package.json 文件,在该文件中指 定 main 的文件存在,引入的就是main属性对应的文件。.js
从文件类型上来说,我实际上是指 .ts , .d.ts 或者 .js

 

相关标签: TypeScript专题