Typescript: 能够超过 TS 并忽略开发人员的特定错误

创建于 2016-06-30  ·  150评论  ·  资料来源: microsoft/TypeScript

开发人员应该能够在 ts 错误上方添加注释,例如

/// TS_IGNORE
let a:string = 1

并让编译器不报告该错误...
在某些情况下,开发人员最了解并希望平息错误报告。

有点像:任何

问候

肖恩

Fixed Suggestion

最有用的评论

就投吧(投不是官方术语,但相同的概念)

const foo: string = 7 as any;

这就是你要找的吗?

所有150条评论

同意。 渴望像 Java 的@SuppressWarnings ,特别是对于这里描述的情况:

下列:

const typeMetadataKey = Symbol('type');

function type(name: string): PropertyDescriptor {
 return Reflect.metadata(typeMetadataKey, name);
}

产生错误: Unable to resolve signature of class decorator when called as an expression.

如下使用时:

class Person {
  @type('string')
  firstName: string;
}

装饰器确实按预期工作并且会编译,但会出现上述错误。

如果你对如何解决这个问题有想法,如果有人想指出正确的方向,很乐意深入研究它。

就投吧(投不是官方术语,但相同的概念)

const foo: string = 7 as any;

这就是你要找的吗?

我只是举了一个例子,不是一个真正的案例(我知道所有关于铸造),我还有其他案例,比如
在构造函数的第一行和其他问题之后调用 super ......

  • 将使从 JS 过渡到 TS 变得更容易+有时您更改一个库并出现大量错误,并且您只是想清理事情,正如您作为开发人员所知道的原因......

这是一个重要的功能

所以像// tslint:disable
甚至可能让您打开/关闭特定检查tsc执行?
_eg:_ const FooBar: string = 'rozzzly'; // tslint:disable-line camelcase

那将是真棒...

我不知道......我认为这可能超出了tsc 。 这就是短绒的用途。

必须能够“闭嘴”:)

我认为有一种情况需要讨论抑制“实验性”功能的错误/警告,比如装饰器,其中 API 有点不稳定,错误可能并不总是准确的。 您只需使用 tsconfig “experimentalDecorators” 字段即可获得(非常具体的)版本,但它仅抑制一种类型的警告。

为了扮演我自己的恶魔拥护者,这可能会鼓励 TypeScript 的新用户抑制他们不理解的警告,而不是了解警告发生的原因。 有了实验性功能,每个人都像是一个新用户——拥有抑制错误的能力可能会让用户对新功能中的错误感到自满,而不是打开问题。

最终,我仍然希望我的 Syntastic 输出是干净的。 这意味着抑制错误。 当然,那将是_after_我打开问题以寻找可能的错误并尝试了解更多信息。 ;)

“闭嘴”的问题是你不知道你从“它”中得到了什么。 那么let a:string = 1number还是string ?,如果还有a另一个声明,它是否合并? 如果有人捕获了这个变量的类型,例如return {a} ; ,他们是否可以分配给{ a : number }{ a: string } ,或两者。

一件基本的事情,错误都是不可忽视的。 错误不会阻止输出的生成,也不会阻止工具。

有不同的机制允许您禁止检查代码的某些部分,例如any 、类型断言(强制转换)和环境声明。

因此,例如,如果您有一个具有“无效”定义的库,您可以将其删除,并将其替换为declare module "blah" { export = any } 。 或declare var $: any就可以了。

由于我通常会回复这些请求,因此我认为您的问题不在于抑制错误。 真正的问题是您遇到了一个您认为没有用的错误。 抑制并不能解决它只是涵盖它的潜在问题,并且具有不一致状态的后果而没有警告。 正确的解决方案是了解您遇到的错误是什么? 它是什么图书馆? 以及为什么编译器给你一个无用的错误......

为此,我们需要更多地了解您的用例。

我们在 TS 2.0 中做了一些工作来解决其中一些潜在问题,例如;

随便使用,这就是“闭嘴​​”的方式,这样做的优点(或实际上缺乏优点)是一个不同的问题

let x: PieInTheSky = <any> 'cake is a lie';

好的,但同样,问题不是专门针对铸造

<any>为您提供了 100% 免于 TypeScript 所有烦人事物的 vanila javascript,那么您还需要什么?

在我的情况下,我称 super 不是构造函数的第一行,需要消除错误

与其试图强迫它接受一个反模式,不如试试这样写:

_ ClassA.ts _

class A {
    constructor() {
        this.init();
    }
    protected init() {
        // does nothing by itself
    }
}

_ ClassB.ts _

class B extends A {
    constructor() {
        super();
        console.log('rest of code from B\'s constructor');
    }
    protected init() {
        console.log('this runs before the rest of code from B\'s constructor');
    }
}

这就是打字稿如此棒的原因,_而且也很烦人_。 它迫使您编写更好的代码,并使您成为更好的开发人员。 转换项目并不好玩; 您可能会认为这是开发人员的“启动”或者“火试”。 :laughing: 但是你学到了很多东西,恕我直言,这是完全值得的。

在我的情况下,我称 super 不是构造函数的第一行,需要消除错误

并使你的代码与 ES6 不兼容......这正是 TypeScript 的主要目的是让 👣 :gun: 脱离你的手的原因。

如果 TypeScript 没有正确解释某些东西,那么它应该被修复而不是“解决”。 现在,在某些情况下,TypeScript 的作用更像是一个 linter,并且还没有“错误”与“警告”的概念。 当它们确实出现时,我可以看到抑制警告。 在我看来,诸如返回后的代码和未使用的参数之类的东西应该是警告,因为它们在语法上是正确的(尽管很愚蠢)。

这是我希望拥有此功能的另一种情况:

interface Animal {
  numberOfLegs: number;
  // a gazillion more properties
}

class Dog implements Animal {
  breed: string;

  constructor(animal: Animal, breed: string) {
    Object.assign(this, animal);
    this.breed = breed;
  }
}

现在有一个来自 ts 的错误:

[ts] 'Dog' 类错误地实现了接口 'Animal'
“Dog”类型中缺少“numberOfLegs”属性

如您所见,编译器是完全错误的,但我不想(也不应该被迫)仅仅为了编译器而从接口复制所有属性。

@DethAriel基本上你要的是一种在类型系统中表达后置条件副作用的方法。 这很有趣,但我有一种感觉,它会导致一些非常复杂的代码。

@aluanhaddad 是的,我完全明白。 但是,除了复制粘贴接口成员之外,我仍然没有看到一个非丑陋的解决方法,这至少是不理想的。 这就是为什么我认为有能力关闭编译器错误输出是有道理的——我们都是聪明人,当我们告诉编译器时,编译器应该信任我们

只需使用接口+类组合

interface Animal {
  numberOfLegs: number;
  // a gazillion more properties
}

interface Dog extends Animal {
}

class Dog  {
  breed: string;

  constructor(animal: Animal, breed: string) {
    Object.assign(this, animal);
    this.breed = breed;
  }
}

谢谢

如果错误不能被<any>删除怎么办?

我使用这里讨论的实验绑定语法https://github.com/Microsoft/TypeScript/issues/3508并且除了不使用它之外,否则我无法让编译器在每个::之前忽略每一行上的错误TS1128: Declaration or statement expected

我使用实验绑定语法

这真的不仅仅是消除一个警告。 解析器不支持它,所以结果树是完全错误的,从这一点开始的所有编译器功能都将不起作用,所以没有类型推断,没有兼容性检查,没有格式化,没有完成,什么都没有。 所以你最好忽略所有错误,或者只是在 .js 文件中工作。

我目前正在将一个巨大的 JS 项目转换为打字稿,并且在运行gulp build命令时进行转换后,我在编译期间看到大约 2000 个 TS 错误,并且大多数错误与未在类或模块上定义的属性有关定义。 我认为在生成输出 JS 文件时,必须有某种方法来抑制这些类型的错误。

这也正是我的情况,我转换了一个使用 ES6 之前的模块作为属性设计构建的应用程序,所以我有一个巨大的 app.namespace1.namespace2.something.views.view 全局对象。

我重写了其中的一部分,并且确实依赖于全局 app.* 对象及其代码中的不同子元素。 我得到的只是大量的“找不到命名空间‘应用’”警告。

我已将所有全局依赖项重构为 globalProxy.ts,因此这是我收到警告的唯一地方,但在此文件顶部添加 //TS-NO-WARNINGS 以清理控制台会很棒从明显的消息...

TS 错误不会阻止代码生成。 您可以选择忽略它们,但是这些告诉您的是编译器无法断言您的代码的正确性。

@zeeshanjan82为什么不使用--allowJs并逐个文件迁移? 使用该设置,您将不会收到来自 JavaScript 源的类型错误。 您还可以使用环境通配符声明来抑制模块解析错误,例如
_globals.d.ts_

declare module '*';

这是错误抑制的另一个用例。

moment 库的维护者忘记将isoWeek作为有效字符串添加到startOfendOf方法的参数枚举中。 它在随后的版本中得到了修复,但在这样做的过程中,他们完全重构了这些单元的处理方式,这会导致我们最终进行过多的返工。

所以我们修复了moment的版本,但是现在我们基本上不能使用isoWeek因为TS抛出错误。 所以此刻卡在岩石和坚硬的地方之间。

你可以只添加一个本地副本。 说一些简单的事情:

// ./overrides/moment.d.ts
declare module "moment";
// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "baseUrl": ".",
        "paths": {
            "moment": ["overrides/moment.d.ts"]  // override definition for moment
        }
    }
}

现在编译器将检查您的本地副本override/moment.d.ts而不是随包提供的副本。 显然,这可以是 moment 声明文件的本地副本,也可以是您需要的一小组东西。

我既没有时间也没有意愿为 3rd 方库维护我自己的类型定义;)

我既没有时间也没有意愿为 3rd 方库维护我自己的类型定义;)

这完全没问题。 只需使用declare module "moment";就相当于declare var $: any用于模块,编译器就不会再打扰你了。

@mhegazy的建议非常好。 完成此操作大约需要 20 秒。 顺便说一下,关于 moment,他们忘记了我正在使用的几个单元,并且他们非常愿意接受我的拉取请求。

添加declare module "moment";的缺点是您将不再对任何与时刻相关的代码进行任何IDE 智能感知或静态类型检查。 并且出现的any往往会渗入周围的代码中,也会关闭那里的许多静态检查。 抑制与单个有问题的枚举值相关的错误需要付出沉重的代价。

@aluanhaddad有一个拉取请求可以解决这个问题,但它被关闭了,取而代之的是另一个引入了isoWeek ),所以不确定那里发生了什么.

关键是,随着 Angular 2 等的采用,这些问题在未来肯定会更频繁地出现,所以我可以想象一种抑制特定错误的方法会很有用。

我有一个节点核心库(网络,节点 6.9 LTS)的问题:

server = net.createServer({ pauseOnConnect: true }, function(connection) { ... }) 
// [ts] severity: 'Error'
message: 'Argument of type '{ pauseOnConnect: boolean; }' is not assignable to parameter of type '{ allowHalfOpen?: boolean; }'.
  Object literal may only specify known properties, and 'pauseOnConnect' does not exist in type '{ allowHalfOpen?: boolean; }'.'

还有 ioredis 库:

var redis = new Redis(CONFIG.redis); 
// [ts] severity: 'Error'
message: 'Only a void function can be called with the 'new' keyword.'

正如@yortus@adamreisnz指出的那样,这是一个常见问题,因为定义文件并不总是正确更新。 此外,如果您必须使用declare module "x";来牺牲 TS 的好处,那么您首先为什么要使用 TS?

您还可以使用缺少的类型来扩充模块,以免失去智能。

好吧,当我写:

if (typeof Symbol === "function" && Symbol.match) {
  // ...
}

如果targetes5 ,打字稿编译器总是会报告错误Cannot find name 'Symbol' es5 ,尽管这段代码确实像我预期的那样运行良好。

所以我同意我们非常需要一些在注释行中工作的控制指令。

declare var Symbol: any;

@gdh1995 @mhegazy或者只是使用将lib标志设置为es2015的真正修复。

@mhegazy谢谢。 我发现这很好用:

declare var Symbol: {
  (description?: anyNotSymbol): symbol;
  readonly match: symbol;
};

@DanielRosenwasser尽管es2015添加了这些有用的功能,但我的项目仅限于与es5兼容,然后Symbol应避免在其他文件中使用。

我现在不明白的是,即使我写了typeof Symbol === "function" ,TypeScript 编译器也会给我错误。 有什么建议吗?

我很想拥有的一种情况是模拟依赖项:

// Test.ts

// Component to test
import {ComponentToTest} from './ComponentToTest';

// Dependency of ComponentToTest to mock
import {Dependency} from './Dependency';

// Mock to replace it with
import {MockedDependency} from './MockedDependency';

Dependency = MockedDependency;

此代码具有在测试组件中模拟依赖项的预期效果,但 TypeScript 抛出一个明显的“无法分配给 'Dependency' 因为它不是变量。” 错误。

我确定回应将是我在错误的树上吠叫,应该使用类似inject-loader但根据我的经验,这些解决方案 A) 很难开始工作/并不总是work 和 B) 并不像上面那样简单。 正如 OP 所提到的,有时开发人员最了解。 我知道这是一个笨拙的解决方案,但它有效,我希望 TS 在这种情况下闭嘴。

此代码具有在测试组件中模拟依赖项的预期效果,但 TypeScript 抛出一个明显的“无法分配给 'Dependency' 因为它不是变量。” 错误。

这是 ES6 中的错误。 所以在未来的某个时候,当引擎本身支持 ES6 模块时,你的测试将需要重写。

或者,您可以让您的ComponentToTest接受Dependency ,并且您的测试可以通过该参数,或者使用测试挂钩允许您在调用方法之前覆盖Dependency的值在ComponentToTest

这是 ES6 中的错误。 所以在未来的某个时候,当引擎本身支持 ES6 模块时,你的测试将需要重写。

啊,很公平,我会放弃它,因为该要求与此问题无关。

或者,您可以让您的 ComponentToTest 接受依赖项的参数,并且您的测试可以通过...

我想这就是我们最终的结果。 必须为一个类重新定义 api 以使其可测试,这是非常蹩脚的,但我想这根本不是 TS 独有的问题。

感谢您的反馈, @mhegazy

我想覆盖对函数参数类型的检查。

我的用例很简单,我有一个这样的函数:

function isValidId(s: string): boolean {}

检查字符串是否遵循某些规则。
它在内部使用并用于验证用户输入 - 我想编写测试以查看当用户插入不是字符串的内容时它是否返回false

严格来说,该函数可以接受任何输入,因为它能够管理它,但由于我们也在内部使用它,我想指定我们想要一个字符串

因此,我想要一些东西来抑制测试中关于错误格式的错误

@rpadovani只需使用any

expect(isValidId(78 as any)).toBe(false);

我也可以用这个。 我们有一种情况,其中 foo(bar: any, baz: any) 被定义为框架的一部分,但在 foo 的某些实现中,bar 未被使用。 打开打字稿错误检查,这会引发错误,因为声明了一个未使用的变量。 它必须声明,因为富的其他版本,使用吧。

@benjaminabbitt似乎foo (_bar: any, baz: any)适合您:不强制使用以"_"开头的名称。

补充:我相信覆盖/忽略特殊错误的能力很重要。

这里具有挑战性的是,人们不断表示想要抑制错误、发布代码片段并获得有效的代码内解决方案以消除这些错误(或发现他们的代码确实存在问题)。 如果不知道真正有问题的错误是什么样的,或者不了解人们想要全局抑制哪些错误,就很难设计此功能。

处理我们希望包含在项目中的第三方 javascript 代码的合适方法是什么?

考虑以下场景。 有一个巨大的库尚未发布到 npm,即使发布了,按原样使用该库也会使我们的应用程序携带大量死代码(摇树无济于事,因为它们将所有内容附加到对象上)。

让我们假设在这种情况下不值得提取这段代码并在 npm 中发布。 我们还有哪些选择?

在我尝试使用这个库时,我提取了我的项目需要的代码并将其作为打字稿文件合并到项目中。 这个问题是打字稿检查这个文件,现在这个文件有很多错误。

对于这种情况,最好在顶部添加/* ts:disable */注释,以便打字稿知道我们不关心文件中可能存在的错误。

请注意,我的项目不再提交任何 javascript 文件,即使它提交了,在尝试将 javascript 纳入流程时,构建过程也会变得更加复杂。

有没有人对如何处理需要在打字稿项目中托管的第三方 javascript 代码有任何建议?

有没有人对如何处理需要托管在打字稿项目中的第三方 JavaScript 代码有任何建议?

不要迁移它们。 保留 .js 文件原样。 而是为他们创建一个 .d.ts 文件。 这就是 .d.ts 文件的用途。

.d.ts 文件可以从以下基本内容开始:

declare var $: any;

然后在您认为合适的情况下以及随着您的需求增长时添加它。

如果我提交 js 文件,这是一个不错的选择。 忽略js文件的项目还有其他选择吗?

如果我提交 js 文件,这是一个不错的选择。 忽略js文件的项目还有其他选择吗?

我不确定我是否理解这个问题。 默认情况下忽略 JS 文件。 所以你选择添加文件。 我的建议是,对于不属于您的外部代码,或者对于您不打算更改的遗留代码,不要费心将其转换为 TS。 首先为他们编写一个 .d.ts 文件。 为此,从简单开始,使用any ,然后随时添加。

我应该说 js 文件没有提交到 git 存储库,因此将代码放在 ts 文件中。 无论如何,我会尝试走你提到的路线并强制提交那些 js 文件。

您不需要提交 .js 文件。 假设您正在使用依赖项,例如 react。 通常你不会在你的 repo 中提交react-0.12.0.js ,但你想使用它。 例如,通常您会将其包含在来自 CDN 的脚本标签中。 假设@types/react不存在,或者您不想使用它。 所以在你的项目中添加一个新的声明文件,命名为declarations.d.ts并添加:

declare module "react"; // just saying the module is of type any

这告诉编译器有一个名为“react”的模块,它只会使用它,不需要包含任何 .js 文件。

因此,如果我想使用一小块 javascript(无法通过 npm/CDN 获得)并且我决定将其提交到我的代码库中,我有两个选择:

选项 1 :将原始代码保留为.js文件并维护一个.d.ts文件来处理类型。

我认为这对@jmlopez-rod 不起作用,因为他不想将 javascript 代码提交到他的 repo,即使他这样做了,他说这会使他的构建过程变得复杂。

选项 2 :将 javascript 包装在打字稿中并处理所有打字稿的错误。

这绕过了“复杂的构建过程”,因为它会将代码视为打字稿……但现在我们遇到了打字稿错误,我们又回到了这个问题线程中的原始讨论。 这是能够禁用打字稿错误的有效用例吗?

我认为这对@jmlopez-rod 不起作用,因为他不想将 javascript 代码提交到他的 repo,即使他这样做了,他说这会使他的构建过程变得复杂。

我不知道为什么它会使您的构建过程复杂化。 您有一个文件"library.js""website.js" ,您决定将“website.js”移动到“website.ts”,只需调用tsc website.ts --outFile website.js ,现在我们又回到了原点从两个 .js 文件开始。 所以不要明白为什么它比以前更复杂......它只是链头的一个额外构建步骤。

这绕过了“复杂的构建过程”,因为它会将代码视为打字稿……但现在我们遇到了打字稿错误,我们又回到了这个问题线程中的原始讨论。 这是能够禁用打字稿错误的有效用例吗?

我不确定我是否完全理解您为什么决定将此文件切换到 ts,并将其与您的项目集成,让其中的类型流入您的其他组件,与您的代码一起构建它,但仍将其保持在不同的标准。

可能是一个在这里有用的例子。 正如@RyanCavanaugh指出的那样,在我看来,所有这些问题都有明确定义的方法来告诉编译器有关类型并避免错误,而不是一起禁用错误并将婴儿与洗澡水一起扔。

我不明白为什么这个环境声明对我不起作用。
我已经像这样定义了 tsconfig.json 的路径定义
"paths": { "js-xlsx": ["./xlsx.d.ts"] }
但我仍然遇到该模块未找到错误。
我尝试添加“fs”、“fs-extra”和“js-xlsx”库,所有这些库都没有响应我的环境声明、转换或添加任何类型,如这里declare var $: any;
@mhegazy

您不需要提交 .js 文件。 假设您正在使用依赖项,例如 react。 通常你不会在你的 repo 中提交 react-0.12.0.js,但你想使用它。 例如,通常您会将其包含在来自 CDN 的脚本标签中。 假设 @types/react 不存在,或者您不想使用它。 所以在你的项目中添加一个新的声明文件,将其命名为 declarations.d.ts 并添加:

声明模块“反应”; // 只是说模块的类型为 any
这告诉编译器有一个名为“react”的模块,它只会使用它,不需要包含任何 .js 文件。

顺便说一下,我知道 fs-extra 库具有像 @types/fs-extra 这样的类型定义,对于 js-xlsx 我们有 ts-xlsx 库,但这太奇怪了,这些技巧对我不起作用:(

顺便说一下,我知道 fs-extra 库具有像 @types/fs-extra 这样的类型定义,对于 js-xlsx 我们有 ts-xlsx 库,但这太奇怪了,这些技巧对我不起作用:(

我认为你的项目还有其他事情要做。

c:\test\9448>npm install @types/fs-extra
[email protected] c:\test\9448
`-- @types/[email protected]
  `-- @types/[email protected]

npm WARN [email protected] No description
npm WARN [email protected] No repository field.

c:\test\9448>type a.ts
import { rmdir } from "fs-extra";
rmdir("c:/test");

c:\test\9448>type tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5"
    }
}
c:\test\9448>tsc --v
Version 2.2.0

c:\test\9448>tsc

c:\test\9448>echo %ERRORLEVEL%
0

是的,也许但是,我无法理解的主要问题是为什么我无法使用给定的方法抑制编译器警告。 顺便说一下,我有https://github.com/AngularClass/angular2-webpack-starter ,我的项目的基础

抑制错误并不一定意味着引入反模式。

我收到一个不正确的错误,

error TS1005: '{' expected.

在这个完美的 JSX 上:

<motor-node ref      = 'menu'
    absoluteSize     = `0, ${this.MENU_BAR_HEIGHT}, 0`
    >
    {menu}
</motor-node>,

它抱怨模板字符串需要{ 。 理想情况下,这应该是固定的,但在那之前,我希望能够有充分的理由抑制错误。

@trusktr ,此错误是解析错误。 抑制它不会改变编译器从现在开始不理解代码的事实,并且文件其余部分的形状处于未定义状态。 这意味着即使此错误被掩盖,推断的类型以及此文件或其他文件中生成的其他错误也是不正确的。

那说。 根据JSX 规范

JSX 属性值:

" JSXDoubleStringCharactersopt "
' JSXSingleStringCharactersopt '
{赋值表达式}
JSX元素

所以我担心错误是正确的,JSX 属性不能有字符串模板文字。 你可以用absolteSize = {...}代替

这个错误是一个解析错误

是的,这就是为什么它应该被修复。

输出是absoluteSize: "0, " + this.MENU_BAR_HEIGHT + ", 0" ,它告诉我编译器一切正常。

哦。 那不好意思了。 我想念你的评论。 我以为你想让错误沉默。

我做了,但你是对的,也许我应该更好地忍受只添加{}

在 TS 2.1 (VS2017 RC) 中,我们收到来自库 JS 文件(位于 /Scripts 中)文件夹(如 TS7027)的报告警告。 能够抑制库文件中的警告/错误或至少在某种全局抑制文件中支持它们(类似于 C# GlobalSupressions.cs)会很好

在 TS 2.1 (VS2017 RC) 中,我们收到来自库 JS 文件(位于 /Scripts 中)文件夹(如 TS7027)的报告警告。

对于无法访问的代码 (TS 7027),请设置--allowUnreachableCode或将其设置在您的tsconfig.json

但是是否可以仅将其应用于库文件。 因为对于“我的代码”,我需要它!

通过使用--alowJs它成为您的代码。 编译器会将它吸入,将其转换为建议的目标,如果您使用--outFile将连接它......它只是它有一个 .js 扩展名。 如果它是“库”代码,我建议为它创建一个 .d.ts 并包含它。

我不知道我们已经打开了 --allowJs - 在 VS2015 中,完全相同的项目不会将 jquery.js、react.js 文件放在脚本中(实际上仅从 html 页面引用

let { value } = browser.waitForPromise(() => {
    return browser.executeAsync(function (method, name, resolve) {
        require(['patron.Locator/patron.Locator.Manager'], function (locator) {
            resolve(result);
        });
    }, method, name);
});

就我而言,第一行是用 TypeScript 编写的,第二行是用 JavaScript 编写的。 它们在不同的上下文中执行,我不想修改 JavaScript 代码。
所以,我们需要一个新的选项,比如/* ts-disable */ /* ts-enable */ (类似 eslint)

就我而言,第一行是用 TypeScript 编写的,第二行是用 JavaScript 编写的。 它们在不同的上下文中执行,我不想修改 JavaScript 代码。

不确定我理解“用 JavaScript 编写的第二行”是什么意思? 你是否将整个语句传递给编译器?

不确定我理解“用 JavaScript 编写的第二行”是什么意思? 你是否将整个语句传递给编译器?

我不想修改该代码,因为它应该按原样传递给 Selenium 服务器。

我不想修改该代码,因为它应该按原样传递给 Selenium 服务器。

如果这是在 .ts 文件中,它将被编译器转换。 编译器会为您删除类型注释。

无论如何,对于这个示例,您只需要declare var browser: any;并且不会出现任何错误。 有关示例,请参阅Playground

如果这是在 .ts 文件中,它将被编译器转换。 编译器会为您删除类型注释。

我需要保证给定的代码在 IE6 和其他旧浏览器中未被篡改。
例如,Node.js 遵循 CommonJS 模块系统,但我的require是其他开发人员在其页面上定义的自定义函数。 这就是为什么我想在不进行任何后修改和预修改的情况下包含该代码。 这对我和我的团队很重要。

无论如何,对于这个示例,您只需要声明 var browser: any; 你不应该得到任何错误。 有关示例,请参阅 Playground。

实际上,浏览器对象是我项目中最受欢迎的对象,没有任何理由可以忽略它。 browser.execute方法也有自己的类型声明。

现在我不确定我是否理解问题所在。 你得到的错误是什么?

我的代码在不同的上下文中执行:节点和浏览器。 第二个上下文的当前问题是类型注释和代码修改。

img-2017-03-07-02-10-28

let { value } = browser.waitForPromise(() => { // node
    return browser.executeAsync( // node
            function (method, name, resolve) { // browser
        require(['patron.Locator/patron.Locator.Manager'], function (locator) {  // browser
            resolve(result);  // browser
        });  // browser
    }, method, name); 
});

这是browser.executeAsync方法的简单实现:

browser.executeAsync  = (...args) => {
   let script = args.shift();

   RPC.Selenium('/session/:sessionId/execute', {
         script: `return (${script}).apply(null, arguments)`, 
         args
    });
}

如您所见,我使用 TypeScript 进行集成测试。

错误信息是什么?

标准误差:

TS2345: Argument of type 'string[]' is not assignable to parameter string
TS7006: Parameter 'error' implicitly has an 'any' type
TS7006: Parameter 'attach' implicitly has an 'any' type
TS7006: Parameter 'message' implicitly has an 'any' type
TS7006: Parameter 'model' implicitly has an 'any' type

等等...

正确定义require

declare function require(v: string[]): any;

正确定义require。

我不能。 就我而言, executeAsync方法包含第三方项目的代码,并且此类require有不同的变体。 上面的代码只是数百个函数之一。
我的愿望很简单——让我在需要的时候排除一些代码:)

您可以将declare function require(v: string[]): any;放在本地。 例如:

// module a.ts
export var ...

declare function require(v: string[], callback: Function);

let { value } = browser.waitForPromise(() => { 
    return browser.executeAsync( 
        function (method, name, resolve) { // browser
            require(['patron.Locator/patron.Locator.Manager'], function (locator) {  // OK
                resolve(result);  
            });  
        }, method, name);
});

您也可以在需要时强制转换为any

let { value } = browser.waitForPromise(() => { // node
    return browser.executeAsync( // node
        function (method, name, resolve) { // browser
            (<any>require)(['patron.Locator/patron.Locator.Manager'], function (locator) {  // browser
                resolve(result);  // browser
            });  // browser
        }, method, name);
});

这应该产生相同的代码。

就我而言,我有一个私有(未导出)抽象类,它只能由两个类扩展:

abstract class IParent {
  static fromConfig(config: ParentConfig): IParent {
    // actual code is 20 lines long, not this simple
    // this throws "Cannot create an instance of the abstract class 'Parent'"
    return new this().applyConfiguration(config);
  }
  abstract method1(): void;
  ...
}

export class FirstChild extends IParent {
  specificMethodForFirstChild() { ... }
  method1() { ... }
  ...
}

export class SecondChild extends IParent {
  specificMethodForSecondChild();
  method1() { ... }
  ...
}

用法:

let first = FirstChild.fromConfig({ ... });
let second = SecondChild.fromConfig({ ... });

// this runs successfully:
(first as FirstChild).specificMethodForFirstChild();
(second as SecondChild).specificMethodForSecondChild();

但是在方法fromConfig()我得到“无法创建抽象类'Parent'的实例:

游乐场代码

  • 我可以复制静态方法并使它们调用一个通用函数,但是当我已经有一个工作代码时听起来很愚蠢。
  • 我不能使类不抽象,因为子类应用了方法实现。
  • 我可以删除抽象方法,但我使用它们在子类上强制执行相同的接口。
  • 我可以使用单独的接口来强制执行它,但是超类将不适合该接口,并且它是静态方法返回的类型。
  • 我无意在抽象类上调用静态方法,我只是想让它在不同的子类上实例化不同的类

编译器不强制派生类构造函数与基类构造函数具有相同的签名。 换句话说,派生类构造函数可以有比基类更多的必需参数。 使用new this()假设所有派生构造函数都没有必需的参数; 这是无法核实的。

如果您确定这是正确的,请考虑将其转换为new (<any>this)(x, y);

好点我没有看到。 你的建议确实有效,我会考虑危险,谢谢。

有没有办法让Module ... was resolved to ..., but '--allowJs' is not set静音? 在我的用例中,有一个构建系统可以解决这个问题,我不需要通过 TSC 传递我的所有代码,所以我想消除这些错误。

'声明模块“someModule”;' 在您的 .d.ts 文件之一中。

或者安装匹配的@types包(如果存在)。

我还有另一个例子说明这什么时候有用:

const Button = (
  content: contentTypes,
  action: React.EventHandler<React.MouseEvent<HTMLDivElement>>,
  disabled: boolean
): JSX.Element => (
  <div className={`Button disabled-${disabled}`} onTouchStart='' onClick={ !disabled ? action : undefined } >
    { content }
    <div className='background'></div>
  </div>
);

这会引发错误,因为 onTouchStart 不接受字符串作为 true 的参数。 但是, onTouchStart=''修复了与某些 css 规则相关的触摸设备上损坏的 css 行为。 我不想全局禁用此错误或重新定义某些 JSX 类型。 我只想在这一行上删除此错误。

onTouchStart={<any>''}

这实际上并不能解决它。
我收到此错误:
error
它在 tsx 语法下被破坏

onTouchStart={'' as any} ,而是(忘记 JSX 使用备用断言语法)

@RyanCavanaugh生成的代码是否符合此功能的合法用例? 我正在使用swagger codegen为节点服务创建 api 客户端。 我还在我的服务器中使用生成的客户端类型,因为它将 swagger 定义转换为 TypeScript 接口,因此这是确保我尊重我自己的 swagger 合同的最简单方法。

不过生成的代码有点奇怪,它有这样的块:

let contentTypeHeader: Dictionary<string>;
if (contentTypeHeader) {
    fetchOptions.headers = contentTypeHeader;
}

如果strictNullChecks处于打开状态,则会出现错误,因此我已为整个项目关闭了该标志。 这很糟糕。 我不想解析生成的打字稿并修改它,但我准备在文件顶部插入类似<tsc strictNullChecks=false />的内容(类似于@alexanderbird的建议)。

这不是对 swagger 代码生成器的更改请求,以生成符合 strictNullChecks 的代码吗?

@mhegazy肯定 - 但这只是此类事件的一个例子。 代码生成在 TypeScript 中有很多有用的方法(比 JavaScript 更有用)。 所以理想情况下,会有一种方法不强迫人们将他们自己的项目拖到他们生成的代码的标准上。

但它们是 :) 您从自动生成工具获得的代码会导致流入您的编译的类型。 如果代码生成工具忽略--strictNullChecks那么您的代码正在观察非误导性类型。
禁用检查只是抑制火警警报。 问题不是警报,而是首先引起火灾的原因。

@mhegazy我可以在由经过充分测试的工具生成的代码中

一个争议较小的例子怎么样——如果生成的代码有一个未使用的本地代码怎么办? 这不会对我的代码造成任何伤害 - 除非我必须在 tsconfig 中关闭noUnusedLocals - 这就是我现在正在做的。

一个争议较小的例子怎么样——如果生成的代码有一个未使用的本地代码怎么办? 这不会对我的代码造成任何伤害 - 除非我必须在 tsconfig 中关闭 noUnusedLocals - 这就是我现在正在做的。

如果你不关心生成的代码,那么它应该在 .js 中,并带有一个伴随的 .d.ts。 这样你就可以检查它,但不必编译它。

打字稿编译器似乎不喜欢与链一起使用的 underscore.js mixins。

_.mixin(){sortFunciton: sortFunc(), otherChainFunc: otherFunction()}

....

someVal = _.chain(someArray)
.sortFunction()
.otherChainFunc()
。价值();

...

一个非常简单的例子是当你为点击创建一个监听器时,例如为 Angular 使用@HostListener() ,如下所示:

@HostListener('click', ['$event'])
onClick(event: MouseEvent) {
    // Code here...
}

如果启用noUnusedLocals ,则会出现以下错误:

ERROR in ./src (20,13): 'onClick' is declared but never used.

有什么办法可以让编译器忽略它吗?

@JeremyCarlsten

_.mixin(){sortFunciton: sortFunc(), otherChainFunc: otherFunction()}

看起来像无效代码。

@leocaseiro为什么它需要是私有的? 在这种情况下, onClick是 angular 最终会使用的方法。 当我们声明在模板中使用的私有变量时,总会发生类似的问题。 如果您确实在模板中使用它们,只需将变量设为公开即可。 这是有道理的,因为您让 angular 使用它们。

嗨@jmlopez-rod,你是对的。

有趣的是,作为公众,它现在已经过去了! 我真的很感谢你的帮助。

@leocaseiro public 是默认的可见性级别,因此您无需指定它。

如果听起来很消极,请提前道歉——我可能错过了一些东西(TS 新手)。
另一个例子(我只使用 TS 来生成 ES5 - 没有强制转换、声明、接口)

// do-as-i-tell-you-start
const factory = () => {
  const _this = [];
  let _value;
  Object.defineProperties(_this, {

    // Error: Property 'getset' does not exist on type 'any[]'.
    // true at at creation but not when used – don't MOM me!
    'method1': { value(){ return _this.getset; } },   

    // Works with property strings – I don't want this
    'method2': { value(){ return _this['getset']; } }, 

    'getset': { get(){ return _value; }, set(value){ _value = value } },
  });
  return _this;
}

在创建时是真的,但在使用时不是 - 不要妈妈!

这正是 TypeScript 的设计目的。 如果您不想使用类型和强制转换,为什么要使用 TypeScript? 正如在此线程中多次指出的那样,它仍然会发出代码,因此您已经自担风险忽略错误。 为什么要尝试简化 TypeScript,目的是什么?

为什么要尝试简化 TypeScript,目的是什么?

这是关于将一​​个团队从 ES5 => ES6(Babel 或 TS)=> TS 转移到所有它的荣耀中 - 一步一步。

我的印象是 TS 是 JS 的一个补充,让你可以在你处于什么级别时介入。
我投诉的原因是提供的虚拟示例引发错误,因此 _does
不生产 ES5_。 IMO 传递 linting 不应强制转换。

除非你没有发出错误,否则它会发出。 所以它确实产生了 ES5。

它没有 - 切换到 Babel - 它起作用了

tsc可以配置为无论类型错误如何都发出输出,请查看noEmitOnError选项。

如果您使用 ts-loader,它还有一个新的transpileOnly选项,它会简单地进行转译而不显示任何错误。

@trusktr谢谢 - 我会试试的 :-)

错误不会阻止输出的生成,也工具

这不是真的。 我们在 webpack 中有一个(很常见 - 它来自 starter)设置,它在生产构建中崩溃并且不输出任何内容。 应该是这样 - 编译器报告错误,程序员返回并修复它们。 为什么在整个团队都忽略它们时使用类型,因为构建正在“工作”? 同样,如果 tsc 无法编译,则自动刷新不起作用(插件是故意这样编写的 - 如果您的代码错误[或编译器认为错误],它不会刷新)。

当 tsc 中存在错误时,抑制错误很有用。 例如,这应该编译:

interface A {
  isEmpty(x: any[] | string | object): boolean;
}

const a: A = <A>{};
a.isEmpty({a: 1});

但在当前的 TS 版本中它失败了。

编辑:固定函数调用(复制错误的行)

经过

a.isEmptyObject({a: 1});

你的意思是

a.isEmpty({a: 1});

?

哦是的。 复制错误的行:/。

当 tsc 中存在错误时,抑制错误很有用。

应该修复阻止发射的错误。 当 tsc 有导致崩溃的错误时,忽略错误的能力极不可能会导致 tsc 突然发出某些内容。

我有一个看起来像这样的导入:

import * as reducers from "./**/reducer.ts"

我先使用 TypeScript,然后是 Babel。 我有一个 babel 插件,它将导入中的*视为全局模式。 TypeScript 抛出一个错误,抱怨.ts ,然后如果.ts被删除,它就找不到模块。

我不确定如何解决这个问题,但我的第一个想法是抑制与此行相关的错误。 我尝试在配置中进行模块映射,但*在那里也被视为通配符并且无法转义。

@lukescott在编译器的范围内的.d.ts:

declare module './**/reducer' {
  export = {
    [reducer: string]: () => void; /* or whatever */
  };
}

这将如何有用的另一个示例:

const req = https.request({
        host: 'www.google.com',
        method:'GET',
        path:'/',
        port: 443,
}, (res) => { 
    console.log(res.connection.getPeerCertificate());
});

getPeerCertificate表示它不存在,因为节点 https (也是 this )中的定义错误

它仍然可以编译并使用大红色下划线,但这样做会非常好

console.log(res.connection.getPeerCertificate()); //ts:disable-line

@trusktr
哎呀看起来我确实搞砸了从产品代码转换它的语法。 是我试图描述的 js plunk。 也许更多的是下划线定义的问题。 但是如果第三方库导致 ts 编译器出现问题,我们难道不能忽略那行代码吗?

+1。 这对于测试很有用,因为我需要确保我的代码在传递给它不期望的东西时抛出错误。

这个有用的特性只是对可能为空的对象的!的泛化。

如果我想把一个库文件带进一个项目中(例如Chartjs),我经常把它保存为一个TS文件(我喜欢把所有的源文件都保留为TS并编译为JS)并用三斜杠ref导入到TS中需要它的文件。 然而,TypeScript 然后无休止地抱怨该文件中的错误(很自然,因为它只是一个保存为 TS 的标准 JS 文件)。

但是,能够添加:

/*ts-errors-disable*/到库文件的开头和/*ts-errors-enable*/到最后会减少不相关的错误输出,但仍然允许开发人员将所有源文件保留为 TS。

还是我应该从根本上不同地做事?

@benfrain好吧,如果存在相应的 TypeScript 定义文件( npm install --save-dev @types/mylibrary )或使用any类型创建您自己的 _.d.ts_ 文件到您的库命名空间会更好/主类第一:

// mylibrary.d.ts
declare module "mylibrary" {
    let mylibrary: any;
    export = mylibrary;
}
// main.ts
import mylibrary = require("mylibrary");
...

我有个问题。 首先是代码,以及 TypeScript 突出显示的错误:

import {Directive, ElementRef, Input, OnChanges, SimpleChange} from '@angular/core'

@Directive({
  selector: '[blankAttr]',
})
export class BlankAttr implements OnChanges {
  @Input('blankAttr') private attrName: string // <--- TS Error: unused variable

  constructor(private el: ElementRef) {}

  public ngOnChanges(changes: {[key: string]: SimpleChange}): void {
    const change: any = changes.attrName 
    const prevValue: any = change.previousValue

    if (prevValue) {
      this.el.nativeElement.removeAttribute(prevValue)
    }
    this.el.nativeElement.setAttribute(change.currentValue, '')
  }
}

我遇到的问题是我需要声明@Input装饰器以允许向该属性传递一个字符串。 但是我只关心该字符串更改时的值。 并且我可以在处理更改事件时获取以前的和当前的值。

我们现在可以有// ts-ignore吗? 还是有另一种方法可以很好地解决这个问题?

@uglow为什么attrName私有的? 这是一个 Angular 修改的变量,以便您可以使用它获取值。 因此,它需要公开。

@jmlopez-rod 我已将其更改为公开,但这并没有改变问题。 TS 说它是一个未使用的变量。

我正在使用 TS 2.4.1,在公开打字稿后停止发出错误。

前:
screen shot 2017-07-26 at 9 53 13 am

后:
screen shot 2017-07-26 at 9 53 39 am

我正在使用 2.3.3。 我会试试 2.4.1。 谢谢😊

这应该包括在内。 我正在使用一个自定义 js 引擎,它允许单个 .js 文件返回一个值。 有关示例,请参阅我的要点。 我使用 TS 生成我的 .js 文件,当然 TS 不知道并抛出:

A 'return' statement can only be used within a function body.

@mhegazy我以多种不同的方式遇到了这种问题。

我目前的情况(整个流程都采用声明模式):

  • 类装饰器需要一个类声明(不是类表达式),而我在一个函数中 - 原则上这可以解决,但不是今天。
  • 好的,没问题,我将表达式声明为
  • 没有骰子,声明现在有一个未使用的名称
  • 好的,没问题我会退货
  • 没有骰子, Return type of public method from exported class has or is using private name
  • ……?

基本上,这里的根本原因是表达式不能被修饰,但是你放弃一切来实现该功能是不合理的。 与此同时,我简单地抑制这个错误是明智的。 如果抑制错误需要我找到相关的 TypeScript 问题并说出类似// TS-LIMITATION:#9448我会很好,尽管我怀疑从您的角度来看这会导致大量新的毫无意义的问题。

如果您为尚未准备好接受的已知问题添加特定的有针对性的抑制,我什至会很好,但前提是要快速完成并且没有太多的设计工作(这将使该机制毫无意义:眨眼:)

当我做类似的事情时,我不想得到无法访问的代码错误(我很高兴在这里注释“关闭无法访问的代码错误”)
if (false){ ...complicated debug code that I dont want to delete/forget... }

因此,TypeScript 编译器仍然缺少“关闭并不要弄乱其他工具”的选项。 通过注释和特定文件甚至 glob 的编译器开关来拥有这个选项对我们来说真的很有用。 我们坚持使用旧版本的工具,因为我们不想失去自动重新加载(当出现错误时,新版本不会自动重新加载)。 所以我们要么关闭有问题的选项 noImplicitAny(我真的不想这样做,我使用 TypeScript 是因为类型检查,并且允许隐式任何 TypeScript 不会给表格带来那么多),或者继续使用旧版本的包。 是的,我在WebPackAwesomeTypeScript加载器中都报告了该错误,但没有人在意。 这个问题已经被忽视了好几个月了。 我看到它与 TypeScript 包完全相同:-(。

@polyglotinc if (!!false) {

@RyanCavanaugh好吧,就此而言, (!true)有效......我什if (false)的忙碌的身体,它会知道if (!true)是同一回事!

@unional SO问题可以写得更清楚一些,也许这就是我们需要编译器告诉我们可能的错误的原因。 请参阅此屏幕截图,其中显示了用户想要抑制的错误

screen shot 2017-08-09 at 12 43 20 am

请注意,在屏幕截图中,我只有一个错误。 那是因为我已经解决了编译器发现的一个问题。

private keyHandlers = {
    'ArrowDown': function ($event: any) {
      this.handleArrowDown($event);
    },
    'ArrowUp': ($event: any) => {
      this.handleArrowUp($event);
    },
  };

用户声称handleArrow*正在被使用,但打字稿没有看到它被使用。 就打字稿而言, this中的this.handleArrowDown($event);可以是任何具有handleArrowDown方法的对象。 使用箭头函数,它现在知道this是类的实例,因此它看到handleArrowUp正在被使用。

另一种选择:使用假第一个参数this

  private keyHandlers = {
    'ArrowDown': function (this: SomeComponent, $event: any) {
      this.handleArrowDown($event);
    },
    'ArrowUp': ($event: any) => {
      this.handleArrowUp($event);
    },
  };

@jmlopez-rod 谢谢。 这些都是不错的选择。 我特别喜欢function(this: SomeComponent, ...) {...}解决方案,因为这是最灵活的。

如果keyHandlers不是类的一部分,则箭头函数不起作用:

const keyHandlers = {
  'ArrowDown': function (this: SomeComponent, $event) {
    this.handleArrowDown($event); // error on accessing private method, filing an issue for it.
  },

  'ArrowUp': ($event) => { // doesn't work, duh
    this.handleArrowUp($event);
  }
}

export class SomeComponent {
  onKeyDown($event) {
    if (typeof keyHandlers[$event.code] === 'function') {
      keyHandlers[$event.code]($event);
    }
  }
  private handleArrowDown(_event) {
    // ...
  }

  private handleArrowUp(_event) {
    // ...
  }
}

另一方面,箭头函数在这种情况下是最直接的。

我正在尝试为 IE9 手动设置window.console以防止console.log使用错误:

if (!window.console)
    window.console = {};

但是我得到error TS2540: Cannot assign to 'console' because it is a constant or a read-only property.这些用例有什么解决方法吗?

@amiraliakbari您可以将window断言为any类型,这有效地让您选择退出类型检查:

(window as any).console = {};

这对我有效地覆盖/禁用console.log全局 - 请注意Project.logging在此之前定义

(window.console as any).___real_log = window.console.log;
window.console.log = function(args) {
  if (Project.logging) return (window.console as any).___real_log(args);
  return;
};

这也比在我的代码中放置if语句要干净得多,因为我可以正常使用console.log

正如#19109 中提到的,我们仍然无法抑制特定错误。

正如#19109 中提到的,我们仍然无法抑制特定错误。

我认为此问题中概述的基本情况已得到解决。 我们可以创建一个新问题来使用错误号跟踪全局错误抑制。 我们一直不愿意以这种方式使用错误代码,因为它们缺乏表现力。

创建 #19139。

此指令仅适用于每个文件,对吗? 是否可以让它在文件夹上工作?

该指令应该一次为一行工作。 如果您在项目中看到很多编译器错误,您可能会检查您是否应该使用不那么严格的编译器选项,例如将noImplicitAny关闭(即,如果不是,则变量隐式any注释)。 您也可以将一些文件保留为 JS 并设置allowJs打开但checkJs关闭。

你为什么关闭这个问题? 解决方案仍然缺失! 为什么你进行了 2 年无意义的讨论,而不是整合一个适当的错误抑制可能性?

@webia1您可能对仍然开放的 #19139 感兴趣。

(在此处添加此评论,因为它可能对像我一样偶然发现此问题的人有用)

我遇到了https://github.com/Microsoft/TypeScript/pull/21602 ,它可能是解决方案。

只需将// @ts-ignore到您的代码中(甚至// @ts-ignore <some code error>仅忽略指定的错误)

在此处使用 TypeScript 2.7.2 对其进行了测试,并且可以正常工作!

(甚至 // @ts-ignore仅忽略指定的错误)。

21602 未合并。 您不能只忽略某些错误。

@RyanCavanaugh你是对的! 我已经更新了我的评论。 谢谢!

到达这里是为了抑制错误 TS2339。

document.getElementById('theme-admin').disabled = false; /* tslint:disable */
document.getElementById('theme-member').disabled = true; /* tslint:disable */
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

kyasbal-1994 picture kyasbal-1994  ·  3评论

seanzer picture seanzer  ·  3评论

blendsdk picture blendsdk  ·  3评论

Antony-Jones picture Antony-Jones  ·  3评论

Zlatkovsky picture Zlatkovsky  ·  3评论