Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: port rules to typescript #785

Merged
merged 7 commits into from Jan 26, 2020
Merged

refactor: port rules to typescript #785

merged 7 commits into from Jan 26, 2020

Conversation

byCedric
Copy link
Member

@byCedric byCedric commented Sep 12, 2019

Description

Part of #659

Motivation and Context

Just finished a couple of things here to get the full @commitlint/rules package to typescript. I'm happy about most of it, but for some, I still have some doubts. I know, I'm sorry, it's a huge PR. But this was the only way. 😅

  1. Strictly typed rule components
    To get a uniform set of rules, we need some types. I looked to the current use cases and tried to come up with a simple draft for the types. Basically, there are Rule, RuleCondition, and RuleOutcome. There are some docblocks in the @commitlint/rules/src/types.ts file, so please take a look. Also added some usage examples below. 😁

  2. Rules are not all using the RuleCondition
    This is something I noticed when combating TypeScript's "Type can be null" errors. I set all rules that do not use the when parameter explicitly to undefined. (you can find them by searching for when = undefined)
    To be honest, I think all rules should still implement the negation, even if it doesn't make sense. Solely to get a uniform way of working with these negations.

  3. Export TargetCaseType from @commitlint/ensure.
    Some of the rules are using ensure.case, to get the value argument correctly typed we need to reuse this type. Exporting this from the package where it "lives" was my best option. We can also define the types in @commitlint/rules, but that didn't feel nice.

Usage examples

I went for a generic-typed Rule interface that allows us to type all 3 parameters strictly. It defaults to never, so if you don't define a generic type, you should not use the value. With this, we can define a casing rule as Rule<ensure.TargetCaseType>, where the 3rd parameter will be strictly typed to ensure.TargetCaseType! 🎊🚀

Example rules

// simple rule without additional settings
const simpleRule: Rule = (parsed, when = 'always') => ...
const sameSimpleRule: Rule<never> = (parsed, when = 'always') => ...

// casing rule that only allow an array of ensure.TargetCaseType as addition settings
const caseRule: Rule<ensure.TargetCaseType[]> = (parsed, when = 'never', value = []) => ...

Full types

/**
 * Rules always have a condition.
 * It can be either "always" (as tested), or "never" (as tested).
 * For example, `header-full-stop` can be enforced as "always" or "never".
 */
export type RuleCondition = 'always' | 'never';

/**
 * Rules match the input either as successful or failed.
 * For example, when `header-full-stop` detects a full stop and is set as "always"; it's true.
 * If the `header-full-stop` discovers a full stop but is set to "never"; it's false.
 */
export type RuleOutcome = [boolean, string?];

/**
 * Rules receive a parsed commit, condition, and possible additional settings through value.
 * All rules should provide the most sensible rule condition and value.
 */
export type Rule<Value = never> = (
    parsed: Commit,
    when?: RuleCondition,
    value?: Value
) => RuleOutcome;

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@byCedric byCedric changed the title Refactor/rules to ts refactor: port rules to typescript Sep 12, 2019
@byCedric
Copy link
Member Author

byCedric commented Sep 12, 2019

Hmm, I'm not sure why Circle CI is erroring... Any idea what is causing this? @marionebl

FAIL  @commitlint/rules/src/footer-empty.test.ts
  ● Test suite failed to run

    Cannot find module 'has-values' from 'index.js'

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:230:17)
      at Object.<anonymous> (node_modules/unset-value/node_modules/has-value/index.js:11:17)

@marionebl marionebl mentioned this pull request Sep 12, 2019
18 tasks
@marionebl
Copy link
Contributor

Hmm, I'm not sure why Circle CI is erroring, but it doesn't look like failed tests. More like failing (jest) processes. Any idea what is causing this? @marionebl

Something related to ts-jest running amok I guess. Will have to investigate in detail...

@byCedric
Copy link
Member Author

byCedric commented Sep 14, 2019

If ts-node is a problem, we can also try Jest + Babel. It seems that this is the recommended way to use TypeScript, but without test-type checking, with according to Jest docs. I don't think the types are necessary during testing, since we also build everything with tsc (where it's tested anyway)

@byCedric
Copy link
Member Author

byCedric commented Oct 20, 2019

I updated this PR to match the latest changes in master. I also did some research on why "the hell" tests would take ±265s, I think it's related to this issue.

In my point of view, we have 2 options here:

  1. Run tests with --maxWorkers=1, that should decrease the amount of times typescript is being compiled. This should result in the tests running way quicker.
  2. Remove ts-jest and use babel-jest to "remove" the typings. TypeScript itself could still be used to check the typings, I think it's included in both yarn build and yarn lint.

Personally, I like 2 more. We don't need actual type checking in the tests, it's already checked when building or linting. I also think using multiple workers is required when porting everything to TS and Jest. What do you think @marionebl / @escapedcat?

@byCedric
Copy link
Member Author

Also, before merging this PR, it might be wise to merge PRs #818 and #819. I'll update them to TypeScript after the merger and include it in this one if we want them. It might be a bit harder to include them after merging this PR.

@byCedric byCedric force-pushed the refactor/rules-to-ts branch 2 times, most recently from 2d07b49 to 13e4f56 Compare January 26, 2020 15:45
@byCedric byCedric merged commit 4cd2208 into master Jan 26, 2020
@byCedric byCedric deleted the refactor/rules-to-ts branch January 26, 2020 17:17
@byCedric byCedric mentioned this pull request Jan 26, 2020
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants