error for I prefixed interface names
Summary: {gif:kosnw403}
Reviewed By: mweststrate
Differential Revision: D33845782
fbshipit-source-id: 2b9bd70e3b2d930e8f4cd8fe7976ac76f43b2496
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a0368a8bbf
commit
75f874a5dd
@@ -145,6 +145,7 @@ module.exports = {
|
|||||||
'flipper/no-electron-remote-imports': [1],
|
'flipper/no-electron-remote-imports': [1],
|
||||||
'flipper/no-console-error-without-context': [2],
|
'flipper/no-console-error-without-context': [2],
|
||||||
'flipper/no-ts-file-extension': 1,
|
'flipper/no-ts-file-extension': 1,
|
||||||
|
'flipper/no-i-prefix-interfaces': 2,
|
||||||
'communist-spelling/communist-spelling': [1, {allow: ['cancelled']}],
|
'communist-spelling/communist-spelling': [1, {allow: ['cancelled']}],
|
||||||
|
|
||||||
// promise rules, see https://github.com/xjamundx/eslint-plugin-promise for details on each of them
|
// promise rules, see https://github.com/xjamundx/eslint-plugin-promise for details on each of them
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ import noConsoleErrorWithoutContext, {
|
|||||||
import noTsFileExtension, {
|
import noTsFileExtension, {
|
||||||
RULE_NAME as noTsFileExtensionRuleName,
|
RULE_NAME as noTsFileExtensionRuleName,
|
||||||
} from './rules/noTsFileExtension';
|
} from './rules/noTsFileExtension';
|
||||||
|
import noIPrefixInterfaces, {
|
||||||
|
RULE_NAME as noIPrefixInterfacesRuleName,
|
||||||
|
} from './rules/noIPrefixInterfaces';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
@@ -26,5 +29,6 @@ module.exports = {
|
|||||||
[noElectronRemoteImportsRuleName]: noElectronRemoteImports,
|
[noElectronRemoteImportsRuleName]: noElectronRemoteImports,
|
||||||
[noConsoleErrorWithoutContextRuleName]: noConsoleErrorWithoutContext,
|
[noConsoleErrorWithoutContextRuleName]: noConsoleErrorWithoutContext,
|
||||||
[noTsFileExtensionRuleName]: noTsFileExtension,
|
[noTsFileExtensionRuleName]: noTsFileExtension,
|
||||||
|
[noIPrefixInterfacesRuleName]: noIPrefixInterfaces,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {TSESLint} from '@typescript-eslint/experimental-utils';
|
||||||
|
import rule, {RULE_NAME} from '../noIPrefixInterfaces';
|
||||||
|
|
||||||
|
const tester = new TSESLint.RuleTester({
|
||||||
|
parser: require.resolve('@typescript-eslint/parser'),
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tester.run(RULE_NAME, rule, {
|
||||||
|
valid: [
|
||||||
|
{
|
||||||
|
code: `interface Icon {name: string}`,
|
||||||
|
filename: __filename,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `interface IOSDevice {version: string}`,
|
||||||
|
filename: __filename,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
{
|
||||||
|
code: `interface IDevice {version: string;}`,
|
||||||
|
filename: __filename,
|
||||||
|
errors: [{messageId: 'noTsInterfacePrefixI'}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {createESLintRule} from '../utils/createEslintRule';
|
||||||
|
|
||||||
|
type Options = [];
|
||||||
|
|
||||||
|
export type MessageIds = 'noTsInterfacePrefixI';
|
||||||
|
export const RULE_NAME = 'no-i-prefix-interfaces';
|
||||||
|
|
||||||
|
export default createESLintRule<Options, MessageIds>({
|
||||||
|
name: RULE_NAME,
|
||||||
|
meta: {
|
||||||
|
type: 'problem',
|
||||||
|
docs: {
|
||||||
|
description: 'Avoid prefixing TS interfaces with "I"',
|
||||||
|
recommended: 'error',
|
||||||
|
},
|
||||||
|
schema: [],
|
||||||
|
messages: {
|
||||||
|
noTsInterfacePrefixI: 'Do not prefix interfaces with "I"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultOptions: [],
|
||||||
|
create(context) {
|
||||||
|
return {
|
||||||
|
TSInterfaceDeclaration(node) {
|
||||||
|
const [l1, l2, l3] = node.id.name;
|
||||||
|
if (
|
||||||
|
l1 === 'I' &&
|
||||||
|
isLetter(l2) &&
|
||||||
|
l2 === l2.toUpperCase() &&
|
||||||
|
isLetter(l3) &&
|
||||||
|
l3 === l3.toLowerCase()
|
||||||
|
) {
|
||||||
|
context.report({
|
||||||
|
node: node.id,
|
||||||
|
messageId: 'noTsInterfacePrefixI',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function isLetter(x: string | undefined): boolean {
|
||||||
|
return typeof x === 'string' && /^[a-z]$/i.test(x);
|
||||||
|
}
|
||||||
@@ -159,7 +159,6 @@ To start Flipper against a specific OnDemand instance, set FB_ONDEMAND flag, e.g
|
|||||||
|
|
||||||
## Guidelines for writing TypeScript
|
## Guidelines for writing TypeScript
|
||||||
* Prefer `type` for React props and state over interfaces
|
* Prefer `type` for React props and state over interfaces
|
||||||
* Don’t prefix interfaces with `I`
|
|
||||||
* Install 3rd party type definitions as dev dependency (e.g. `yarn add @types/lodash --dev`)
|
* Install 3rd party type definitions as dev dependency (e.g. `yarn add @types/lodash --dev`)
|
||||||
|
|
||||||
## Submitting a diff / PR
|
## Submitting a diff / PR
|
||||||
|
|||||||
Reference in New Issue
Block a user