让javascript文件知道他们的打字稿定义文件

时间:2017-10-27 21:29:10

标签: javascript typescript .d.ts

Typescript允许您为本地javascript文件编写.d.ts定义文件,如下所示:

src/
  main.js
  imported.js
  imported.d.ts

main.js

import { func } from './imported';
console.log(func("1", "1"));

imported.js

export const func = (numVal, strVal) =>
  `The number is ${numVal}, the string is ${strVal}`;

imported.d.ts

export const func: (numVal: number, strVal: string) => string;

使用选项noImplicitAny

会出现以下错误
src/imported.js(1,22): error TS7006: Parameter 'numVal' implicitly has an 'any' type.
src/imported.js(1,30): error TS7006: Parameter 'strVal' implicitly has an 'any' type.
src/main.js(3,18): error TS2345: Argument of type '"1"' is not assignable to parameter of type 'number'.

最后一个错误是好的,当我们应该传递一个数字作为第一个参数时,阻止我们传递一个字符串。但对于前两个,在导入的javascript文件中,它不知道已定义参数的类型。这可以防止您使用noImplicitAny,但是当您(例如)将numValue传递给期望字符串的函数时,也会阻止您发生错误。

是否可以让javascript文件在typescript中知道它们的定义,最好不要修改原始的javascript。

1 个答案:

答案 0 :(得分:1)

虽然javascript文件无法识别其定义文件,但是Typescript 2.3增加了对使用JSDoc注释进行类型检查的支持。

将项目更改为:

src/
  main.js
  imported.js

imported.js

/**
 * @return {string} 
 * @param {number} numVal 
 * @param {string} strVal 
 */
export const func = (numVal, strVal) =>
  `The number is ${funcs.func3(numVal)}, the string is ${strVal}`;

main.js

import { func } from './imported';

/**
 * Works fine
 * @param {number} number 
 */
const mainFunc1 = (number) =>
  func(number, "Hello");      

/**
 * Argument of type 'string' is not assignable to parameter of type 'number'
 * @param {string} string 
 */
const mainFunc2 = (string) =>
  func(string, "Hello");

现在,typescript编译器知道numVal是一个数字,而strVal是一个字符串。尝试将numVal传递给不接受数字的函数,同时导致错误。 @return中的func在技术上是多余的,因为它知道它返回字符串(即使没有JSDoc也会知道),但这对于一致性来说是好的。

虽然这确实需要修改原始javascript,但它只使用注释来执行此操作。

限制

这没有所有的完整Typescript类型检查的功能,但它的大部分方式都存在。例如,如果您有一个返回对象的模块,则包含键入的键:

/**
 * @param {number} num 
 */
const func1 = (num) => num * 2;

export default {
  func1,
}

然后用:

消费它
import imported from './module';

imported.func1(3);    // This is okay
imported.func1("3");  // This is an error
imported.func2(3);    // This is also okay, but it shouldn't be

使用javascript文件时,这不会出错,因为它没有为默认导出生成类型,因此无法确认func2不存在。在Typescript中,它会告诉你Property 'func2' does not exist on type '{ func: (num: number) => number; }'. Did you mean 'func'?,而不必明确声明默认导出的类型。

Typescript 2.5

Typescript 2.5还添加了对JSDoc类型断言的支持,例如:

// Argument of type 'string | number' is not assignable to parameter of type 'number'.
const func1 = () =>
  func(funcReturnsNumberOrString(true), "Hi");

// Fine
const func2 = () =>
  func(/** @type {number} */ (funcReturnsNumberOrString(true)), "Hi");

/**
 * @returns { number | string }
 * @param {boolean} bool
 */
const funcReturnsNumberOrString = (bool) =>
  bool ? 2 : "2";

在这种情况下,我们知道funcReturnsNumberOrString会返回一个数字,所以我们可以告诉Typescript。