Skip to content

Enable ban-types lint rule #19586

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

Merged
4 commits merged into from
Nov 29, 2017
Merged

Enable ban-types lint rule #19586

4 commits merged into from
Nov 29, 2017

Conversation

ghost
Copy link

@ghost ghost commented Oct 30, 2017

Functionis unsafe as any function is assignable to it and it can be called with arbitrary arguments.
There are a few places where we just need something to be a Function for the purpose of having a stack trace but we don't ever actually call it.

Disabled running this rule on Symbol since we use that to mean something else.

@ghost ghost mentioned this pull request Oct 30, 2017
@ghost ghost force-pushed the ban-types branch from f121573 to 60aecff Compare October 30, 2017 22:39
@ghost ghost requested a review from weswigham October 31, 2017 15:12
@@ -2,7 +2,9 @@ namespace Harness.Parallel.Worker {
let errors: ErrorInfo[] = [];
let passing = 0;

type Executor = {name: string, callback: Function, kind: "suite" | "test"} | never;
type MochaCallback = (this: Mocha.ITestCallbackContext, done: MochaDone) => void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this should be an ISuiteCallbackContext for "suite" and only this context for "test". Also gives you your answer for the todo below: this callback type (as written, not corrected) would be correct there, I believe.

(before as any) = (cb: Function) => beforeFunc = cb;
let afterFunc: Function;
(after as any) = (cb: Function) => afterFunc = cb;
let beforeFunc: () => void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure you don't want to write type Callable = () => void somewhere and use it everywhere just to reduce the verbosity around places like here? Callback types have a lot of sigils and are visually noisy because of it.

@@ -54,7 +54,7 @@ namespace ts.server {
}

// Disable sourcemap support for the duration of the test, as sourcemapping the errors generated during this test is slow and not something we care to test
let oldPrepare: Function;
let oldPrepare: {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While technically valid because of the any casting; this feels unfortunate.

@@ -4455,7 +4455,7 @@ namespace ts.projectSystem {

describe("cancellationToken", () => {
// Disable sourcemap support for the duration of the test, as sourcemapping the errors generated during this test is slow and not something we care to test
let oldPrepare: Function;
let oldPrepare: {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed one ;)

tslint.json Outdated
"ban-types": {
"options": [
["Object", "Avoid using the `Object` type. Did you mean `object`?"],
["Function", "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can change this to refer to ts.AnyFunction now.

Copy link
Member

@weswigham weswigham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a style POV it seems fine now; it was mostly editing code I wrote anyway, but I defer to @mhegazy for the final say, since he commented on this rule in your other PR though.

@ghost
Copy link
Author

ghost commented Nov 17, 2017

@mhegazy Could you review?

* Safer version of `Function` which should not be called.
* Every function should be assignable to this, but this should not be assignable to every function.
*/
export type AnyFunction = (...args: never[]) => {} | null | undefined | void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use something more specific in each location, e.g. in an input position, either (...args: any[]): T if you care about input (e.g. memoize) or (...args: any[]): void if you do not care about the output (e.g. assert)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is more specific as it can't be called (with arguments at least) and the return value can't be used without casting. If we use ...args: any[] we can pass in a function taking a number but then call it on a string and there will be no warning at compile-time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most of these are not called, e.g. getFunctionName, assert,, fail, etc.. and we never call them with null or void.. and the ones that accept undefined are usually marked with optional parameters..
for these it seems more correct to jut have (...args: any[])=>void or (...args: never[]) => void if you want to be strict.

@ghost ghost merged commit b8f22f5 into master Nov 29, 2017
@ghost ghost deleted the ban-types branch November 29, 2017 20:54
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants