From 2c532992c7dc27e60c956f1db1d1bfce422d26c7 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 16 Dec 2016 14:07:40 -0800 Subject: [PATCH 1/2] Add `interface-over-type-literal` rule --- docs/_data/rules.json | 18 ++++--- docs/rules/array-type/index.html | 2 +- .../interface-over-type-literal/index.html | 12 +++++ docs/rules/no-empty-interface/index.html | 2 - src/rules/interfaceOverTypeLiteralRule.ts | 49 +++++++++++++++++++ src/rules/noEmptyInterfaceRule.ts | 1 - .../interface-over-type-literal/test.ts.lint | 5 ++ .../interface-over-type-literal/tslint.json | 5 ++ 8 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 docs/rules/interface-over-type-literal/index.html create mode 100644 src/rules/interfaceOverTypeLiteralRule.ts create mode 100644 test/rules/interface-over-type-literal/test.ts.lint create mode 100644 test/rules/interface-over-type-literal/tslint.json diff --git a/docs/_data/rules.json b/docs/_data/rules.json index c5b67f588ce..d80fd956535 100644 --- a/docs/_data/rules.json +++ b/docs/_data/rules.json @@ -48,9 +48,9 @@ ] }, "optionExamples": [ - "[true, array]", - "[true, generic]", - "[true, array-simple]" + "[true, \"array\"]", + "[true, \"generic\"]", + "[true, \"array-simple\"]" ], "type": "style", "typescriptOnly": true @@ -269,6 +269,15 @@ "type": "style", "typescriptOnly": true }, + { + "ruleName": "interface-over-type-literal", + "description": "Prefer an interface declaration over `type T = { ... }`", + "rationale": "style", + "optionsDescription": "Not configurable.", + "options": null, + "type": "style", + "typescriptOnly": true + }, { "ruleName": "jsdoc-format", "description": "Enforces basic format rules for JSDoc comments.", @@ -606,9 +615,6 @@ "rationale": "An empty interface is equivalent to its supertype (or `{}`).", "optionsDescription": "Not configurable.", "options": null, - "optionExamples": [ - "true" - ], "type": "typescript", "typescriptOnly": true }, diff --git a/docs/rules/array-type/index.html b/docs/rules/array-type/index.html index 4595a595fd1..cd36ec3c628 100644 --- a/docs/rules/array-type/index.html +++ b/docs/rules/array-type/index.html @@ -31,4 +31,4 @@ "array-simple" ] } ---- +--- \ No newline at end of file diff --git a/docs/rules/interface-over-type-literal/index.html b/docs/rules/interface-over-type-literal/index.html new file mode 100644 index 00000000000..49b4031e849 --- /dev/null +++ b/docs/rules/interface-over-type-literal/index.html @@ -0,0 +1,12 @@ +--- +ruleName: interface-over-type-literal +description: 'Prefer an interface declaration over `type T = { ... }`' +rationale: style +optionsDescription: Not configurable. +options: null +type: style +typescriptOnly: true +layout: rule +title: 'Rule: interface-over-type-literal' +optionsJSON: 'null' +--- \ No newline at end of file diff --git a/docs/rules/no-empty-interface/index.html b/docs/rules/no-empty-interface/index.html index a2858364866..cd2fcfec4f6 100644 --- a/docs/rules/no-empty-interface/index.html +++ b/docs/rules/no-empty-interface/index.html @@ -4,8 +4,6 @@ rationale: 'An empty interface is equivalent to its supertype (or `{}`).' optionsDescription: Not configurable. options: null -optionExamples: - - 'true' type: typescript typescriptOnly: true layout: rule diff --git a/src/rules/interfaceOverTypeLiteralRule.ts b/src/rules/interfaceOverTypeLiteralRule.ts new file mode 100644 index 00000000000..47e97376e0d --- /dev/null +++ b/src/rules/interfaceOverTypeLiteralRule.ts @@ -0,0 +1,49 @@ +/** + * @license + * Copyright 2013 Palantir Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as ts from "typescript"; + +import * as Lint from "../index"; + +export class Rule extends Lint.Rules.AbstractRule { + /* tslint:disable:object-literal-sort-keys */ + public static metadata: Lint.IRuleMetadata = { + ruleName: "interface-over-type-literal", + description: "Prefer an interface declaration over `type T = { ... }`", + rationale: "style", + optionsDescription: "Not configurable.", + options: null, + type: "style", + typescriptOnly: true, + }; + /* tslint:enable:object-literal-sort-keys */ + + public static FAILURE_STRING = "Use an interface instead of a type literal."; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithWalker(new Walker(sourceFile, this.getOptions())); + } +} + +class Walker extends Lint.RuleWalker { + public visitTypeAliasDeclaration(node: ts.TypeAliasDeclaration) { + if (node.type.kind === ts.SyntaxKind.TypeLiteral) { + this.addFailureAtNode(node.name, Rule.FAILURE_STRING); + } + super.visitTypeAliasDeclaration(node); + } +} diff --git a/src/rules/noEmptyInterfaceRule.ts b/src/rules/noEmptyInterfaceRule.ts index 3c6911de923..844ee5611b9 100644 --- a/src/rules/noEmptyInterfaceRule.ts +++ b/src/rules/noEmptyInterfaceRule.ts @@ -27,7 +27,6 @@ export class Rule extends Lint.Rules.AbstractRule { rationale: "An empty interface is equivalent to its supertype (or `{}`).", optionsDescription: "Not configurable.", options: null, - optionExamples: ["true"], type: "typescript", typescriptOnly: true, }; diff --git a/test/rules/interface-over-type-literal/test.ts.lint b/test/rules/interface-over-type-literal/test.ts.lint new file mode 100644 index 00000000000..4403010870f --- /dev/null +++ b/test/rules/interface-over-type-literal/test.ts.lint @@ -0,0 +1,5 @@ +type T = { x: number; } + ~ [Use an interface instead of a type literal.] + +type U = string; +type V = { x: number; } | { y: string; }; diff --git a/test/rules/interface-over-type-literal/tslint.json b/test/rules/interface-over-type-literal/tslint.json new file mode 100644 index 00000000000..dfcff017ebf --- /dev/null +++ b/test/rules/interface-over-type-literal/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "interface-over-type-literal": true + } +} \ No newline at end of file From 5bd95e1a6aa0c6fb72fe772036e9840699194be0 Mon Sep 17 00:00:00 2001 From: Noah Chen Date: Sat, 17 Dec 2016 11:04:23 -0800 Subject: [PATCH 2/2] Update interfaceOverTypeLiteralRule.ts --- src/rules/interfaceOverTypeLiteralRule.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/interfaceOverTypeLiteralRule.ts b/src/rules/interfaceOverTypeLiteralRule.ts index 47e97376e0d..2deba207ca1 100644 --- a/src/rules/interfaceOverTypeLiteralRule.ts +++ b/src/rules/interfaceOverTypeLiteralRule.ts @@ -23,7 +23,7 @@ export class Rule extends Lint.Rules.AbstractRule { /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { ruleName: "interface-over-type-literal", - description: "Prefer an interface declaration over `type T = { ... }`", + description: "Prefer an interface declaration over a type literal (`type T = { ... }`)", rationale: "style", optionsDescription: "Not configurable.", options: null,