-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Revisiting _ underscore for unused parameters: create unused
type
#29202
Comments
I don't think adding a type solves anything. It actually loses type information: Sometimes you need to declare the type of a parameter even if you don't use is. For example in methods of a base class that are meant to be overridden. |
Haven't run across that scenario that often, perhaps an example might help? In any case, off the top of my head I can think of something like myMethod(param: unused | MyType) {
//
} If it's unused, then |
interface Options {}
class Base {
constructor(options: Options) {
this.init(options);
}
init(_options: Options) {
// can be overridden by a subclass
// the parameter needs to be there so the method in the subclass knows that parameter is available
}
}
That could be very confusing if that |
It's hard to talk about what's right or wrong in something that we're making up as we go. Instead it might be of more value to the community to consider things such as convenience, playing well with other tools, and separation of concerns between syntax and compiler logic. As far as ✨ magic ✨ goes, subjective as it may be, seems no more magical than a leading underscore. Moreover, the issue for this feature was opened and merged in less than 24 hours, leaving little room for community feedback and a proper discussion during its inception, while the merge request itself has 50% of 👎 . Once merged, several different points and propositions were made regarding issues we could face down the line, which we now are. In any case, the objective of this issue is not to push the specific syntax I've proposed above, but rather to ensure that we find a lasting and viable solution to unused parameters. In terms of playing well with other tools and separation of concerns, I do believe my proposal is a step in the right direction. Convenience, again, is subjective, so we may yet find a better solution! |
As
I don't see this as a reason enough to add another keyword/type. Having a The way you have your third-party tools configured should not affect the development of a language. |
Thanks, updated original post :) In any case, the impact would be very low. For example, in the entire DefinitelyTyped repo there are only three instances of
Perhaps I should have expressed myself better: it only works nice with As per point 9 of the Design Goals, Use a consistent, fully erasable, structural type system. If the type system introduces an underscore "idiom" in order for it to work properly when one of its options is activated ( Moreover, coming back to the ✨magic✨ discussion we were having earlier, the underscore would probably go against point 7 of Non Goals: Introduce behaviour that is likely to surprise users. Instead have due consideration for patterns adopted by other commonly-used languages. While the pattern may be common, having variable names linked to compiler options for the type system is certainly surprising.
And that is by no means the angle I'm going for here. I appreciate that you care about my particular dev environment, but rest assured, it is working quite fine. The idea behind this issue is not to discuss the particulars of how this feature interacts with a particular dev environment or tool, but rather to recognize that there is room for improvement. Seeing that this feature was introduced in less than a day and with a non-negligible amount of controversy, we have more than enough grounds for at least revisiting it. I'm not saying that my particular solution be the one we go for, it's just a starting point. |
The name of a function parameter is not part of its type, or signature. declare function foo (a : number) : void;
declare function bar (_a : number) : void; The above are the same type, and those types do get erased. Parameter names just aren't part of a function's type. |
Any "improvement" can only be recognized in some context... that's why you keep getting asked. Nobody wants a change for change's sake - every change we make is targeted at satisfying particular use-cases or issues. I don't see us adding some new type variant just for tracking the suppression of the Unless you can present an actual reason why the other options available fail in some context and why adding behavior to TS is the best way to improve this scenario in that context, I don't see us doing anything like this in the near future. Plus, enumerating that context lets us explore likely more fruitful alternatives to alleviate whatever inconvenience prompted this. |
At the very least, allow us to use I run into this all the time - where I'm adhering to some interface or abstract method and I just don't need one of the parameters that is being passed down. Linters for Javascript have the logic that reports any unused parameters after the last used parameter. For example, if It's not clear how to work around this in Typescript. While I agree that |
@aryzing in Electron, event handles are the case where the const handleEvent = (_ipcEvent: Electron.Event, result: string) => { // tslint error
/// code
} |
? type unused = unknown;
const x = (_event: unused, result: string) { |
After revisiting this I still think allowing multiple underscores is a good thing. It cuts down on noise and immediately indicates intent to ignore while keeping types intact, which is important for a variety of reasons. |
My solution: prefix unused parameter name with " function handleEvent(_unusedEvent: Event, result: string) { ... } Two rationales behind this:
|
At the very least, a function parameter should not be considered to be "unused" if a parameter that comes after it is used. In that case, the "unused" parameter is actually serving a purpose by taking up a slot in the argument list. function fun(a, b) {
// The `a` parameter should not be considered "unused"
console.log(b);
} |
Why not just detect that |
Seems @mjackson hit the nail on the head -- I take my suggestion back. If the compiler can be tweaked to work as described above, that may be all we need. |
You could declare a type alias for this: type unused = unknown; And tweak the linter to understand that it means "unused parameter" and should only be used in function parameters. |
This has a very high ratio of downvotes and doesn't seem like a good solution to the problem. If you need more advanced configuration (only allow me to suppress with a prime number of underscores, etc), there are widely-available highly-configurable linters for the purpose. The check as exists in TS is straightforward and we don't really want to add more lint-like checks.
function fun(a, b) {
// The `a` parameter should not be considered "unused"
console.log(b);
} I feel like this misapprehends the point of a "no unused" check. It's a useful lint because it detects straightforward mistakes like this function fun(a, b) {
alert(`Welcome to ${b}, ${b}, I hope you have a nice day`);
} where you meant to write function fun(a, b) {
alert(`Welcome to ${a}, ${b}, I hope you have a nice day`);
} |
Search Terms
_, underscore, noUnusedParameters, --noUnusedParameters, tslint, ts-lint, #9458, palantir/tslint#3442
Suggestion
Create an
unused
type for function parameters that are not used.Use Cases
Can be used to clearly state unused parameters, while still playing nice with
--noUnusedParameters
and linters enforcing variable name conventions.May also help in cases such as
_
#14154 - destructuring will fail at runtime if argument is not an objecttype Foo<usused> = { }
?Examples
1. Unused parameter
2. Using unused parameter is an error
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: