简体   繁体   English

使javascript文件知道其打字稿定义文件

[英]Make javascript files aware of their typescript definition files

Typescript allows you to write .d.ts definition files for your local javascript files like so: Typescript允许您为本地javascript文件编写.d.ts定义文件,如下所示:

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

main.js main.js

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

imported.js imported.js

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

imported.d.ts imported.d.ts

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

This gives the following errors, with the option noImplicitAny : 使用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'.

The last error is good, that's stopping us from passing a string when we should have passed a number as the first parameter. 最后一个错误是好的,当我们应该将数字作为第一个参数传递时,这将阻止我们传递字符串。 But for the first two, within the imported javascript file, it's not aware that the type of the parameter has been defined. 但是对于前两个,在导入的javascript文件中,尚不清楚参数的类型已定义。 This prevents you from being able to use noImplicitAny, but also stops you from errors when you, for example, pass in numValue to a function expecting a string. 这将使您无法使用noImplicitAny,而且还会使您避免错误(例如,将numValue传递给需要字符串的函数)。

Is it possible to make javascript files aware of their definitions within typescript, preferably without modifying the original javascript. 是否有可能使javascript文件知道其在打字稿中的定义,最好不修改原始javascript。

While javascript files can't be made aware of their definition files, Typescript 2.3 added support for type checking using JSDoc comments. 尽管无法使javascript文件知道其定义文件,但Typescript 2.3增加了对使用JSDoc注释进行类型检查的支持。

Changing the project to: 将项目更改为:

src/
  main.js
  imported.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 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");

Now the typescript compiler is aware that numVal is a number, and strVal is a string. 现在,打字稿编译器已经知道numVal是一个数字,而strVal是一个字符串。 Trying to pass numVal to a function that doesn't accept a number while result in an error. 试图将numVal传递给不接受数字的函数会导致错误。 The @return in func is technically redundant here, as it knows it's returning string (it would know that even without the JSDoc), but it's good for consistency. func@return在技​​术上在这里是多余的,因为它知道它正在返回字符串(即使没有JSDoc,它也会知道),但这对保持一致性很有好处。

While this does require modifying the original javascript, it only uses comments to do so. 尽管这确实需要修改原始的javascript,但它仅使用注释来进行修改。

Limitations 限制

This doesn't have all of the features of full Typescript type checking, but it's most of the way there. 它不具备完整Typescript类型检查的所有功能,但在大多数情况下都是如此。 For example, if you have a module that returns an object, containing typed keys: 例如,如果您有一个返回对象的模块,其中包含键入的键:

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

export default {
  func1,
}

And then consume it with: 然后使用:

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

With javascript files, this won't error, as it hasn't generated a type for the default export, so it can't confirm that func2 doesn't exist. 对于javascript文件,这不会出错,因为它没有为默认导出生成类型,因此无法确认func2不存在。 Whereas in Typescript, it would tell you Property 'func2' does not exist on type '{ func: (num: number) => number; }'. Did you mean 'func'? 而在Typescript中,它将告诉您Property 'func2' does not exist on type '{ func: (num: number) => number; }'. Did you mean 'func'? Property 'func2' does not exist on type '{ func: (num: number) => number; }'. Did you mean 'func'? , without having to explicitly declare the type of the default export. ,而不必显式声明默认导出的类型。

Typescript 2.5 打字稿2.5

Typescript 2.5 also added support for type assertion with JSDoc, for example: 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";

In this case we know that funcReturnsNumberOrString returns a number, so we can tell Typescript as such. 在这种情况下,我们知道funcReturnsNumberOrString返回一个数字,因此我们可以这样告诉Typescript。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM