Skip to content

Implement New Optional Type Checking Flag "veryStrictArity" #54449

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

Closed
4 tasks done
topce opened this issue May 30, 2023 · 11 comments
Closed
4 tasks done

Implement New Optional Type Checking Flag "veryStrictArity" #54449

topce opened this issue May 30, 2023 · 11 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@topce
Copy link

topce commented May 30, 2023

Suggestion

πŸ” Search Terms

  • strict arity checks
  • function parameter count
  • function arity mismatch
  • stricter type checking
  • veryStrictArity

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code (if option is disabled) otherwise πŸ’£
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

Add an optional type checking flag veryStrictArity to enforce stricter checking of the arity of methods.

πŸ“ƒ Motivating Example

interface I {
  hi(a: string, b: string): void;
}

class A implements I {
  hi(a: string): void { // Should raise an error with `veryStrictArity` flag.
    throw new Error("Method not implemented." + a);
  }
}

πŸ’» Use Cases

Consider a case where a method defined in a class doesn't strictly adhere to the parameter count defined in its interface:

interface I {
  hi(a: string, b: string): void;
}

class A implements I {
  hi(a: string): void { // No TypeScript error here currently, but should raise an error with the `veryStrictArity` flag.
    throw new Error("Method not implemented." + a);
  }
}
abstract class Animal {
  abstract makeSound(sound?: string): void;
}

class Dog extends Animal  {
  makeSound() { // No TypeScript error here and no error with the `veryStrictArity` flag, as 'sound' is optional.
    console.log("Woof! Woof!");
  }
}

Despite the veryStrictArity flag being enabled, the makeSound method in class Dog would not raise an error because the sound parameter is optional in the abstract method declaration.

The proposed veryStrictArity flag could help in enforcing the presence of callback parameters, that is currently not possible in Typescript.

@topce
Copy link
Author

topce commented May 30, 2023

this issue should be fixed by PR #54441

@topce
Copy link
Author

topce commented May 30, 2023

it is also connected with #46881
that was wrongly created as bug

@fatcerberus
Copy link

This would break totally reasonable code like array.map(x => x) because .map takes a callback with 3 parameters. I still stand by what I said here: #46881 (comment)

@MartinJohns
Copy link
Contributor

MartinJohns commented May 30, 2023

What problem are you actually trying to solve? Your use case doesn't describe why this should be an error. Providing a function that takes fewer arguments is not an error, it doesn't lack type safety. If a method can fulfill its purpose with fewer arguments, then that's perfectly fine.

@topce
Copy link
Author

topce commented May 30, 2023

@MartinJohns
Actually in all OOP that I know languages this is considered error including C# Java Pascal etc
If you have interface with 2 parameters
You add new parameter on second position
Your class that implement first version of interface
Is broken without any compile time error
It will also allow Typescript to finally after 10 years can have optional parameters in callback function also to describe better signature of callback function

@MartinJohns
Copy link
Contributor

MartinJohns commented May 30, 2023

If that's your answer, then you need to remove the last check from the viability checklist. This is an explicit non-goal of TypeScript:

Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.

Your argument that the class "is broken" also doesn't make sense. It's not broken, it works fine, just without the unnecessary argument.

Trying to treat TypeScript exactly like other languages is a recipe for disaster and bad code.

@topce
Copy link
Author

topce commented May 30, 2023

This would break totally reasonable code like array.map(x => x) because .map takes a callback with 3 parameters. I still stand by what I said here: #46881 (comment)
Well that depends how you define type of map .
You can check some code examples that I provided in PR namely mymap

Indeed it will break compilation of lot of code that why bu default is disabled
but if types of map, forEach ... are change similar way like done on my examples in PR maybe we find some real bugs

for example when I turn it in on TypeScript repo there are

Found 1293 errors in 46 files.

Errors Files
9 src/compiler/binder.ts:1066
34 src/compiler/builder.ts:337
9 src/compiler/builderState.ts:135
568 src/compiler/checker.ts:1479
48 src/compiler/commandLineParser.ts:234
13 src/compiler/core.ts:252
9 src/compiler/debug.ts:282
74 src/compiler/emitter.ts:786
10 src/compiler/factory/nodeConverters.ts:131
6 src/compiler/factory/nodeFactory.ts:1030
4 src/compiler/factory/parenthesizerRules.ts:405
2 src/compiler/factory/utilities.ts:731
11 src/compiler/moduleNameResolver.ts:113
28 src/compiler/moduleSpecifiers.ts:235
14 src/compiler/parser.ts:468
2 src/compiler/performance.ts:137
67 src/compiler/program.ts:356
24 src/compiler/resolutionCache.ts:509
7 src/compiler/scanner.ts:387
4 src/compiler/semver.ts:71
13 src/compiler/sourcemap.ts:411
8 src/compiler/symbolWalker.ts:44
15 src/compiler/sys.ts:259
5 src/compiler/tracing.ts:105
9 src/compiler/transformer.ts:127
4 src/compiler/transformers/classFields.ts:1419
39 src/compiler/transformers/declarations.ts:260
3 src/compiler/transformers/declarations/diagnostics.ts:223
5 src/compiler/transformers/destructuring.ts:224
6 src/compiler/transformers/es2015.ts:2630
5 src/compiler/transformers/es2017.ts:295
1 src/compiler/transformers/esDecorators.ts:2100
6 src/compiler/transformers/generators.ts:743
9 src/compiler/transformers/jsx.ts:253
3 src/compiler/transformers/legacyDecorators.ts:532
3 src/compiler/transformers/module/module.ts:270
1 src/compiler/transformers/module/node.ts:95
3 src/compiler/transformers/module/system.ts:229
5 src/compiler/transformers/ts.ts:287
1 src/compiler/transformers/utilities.ts:126
62 src/compiler/tsbuildPublic.ts:307
69 src/compiler/utilities.ts:664
14 src/compiler/utilitiesPublic.ts:549
28 src/compiler/watch.ts:226
15 src/compiler/watchPublic.ts:473
18 src/compiler/watchUtilities.ts:151

@topce
Copy link
Author

topce commented May 30, 2023

If that's your answer, then you need to remove the last check from the viability checklist. This is an explicit non-goal of TypeScript:

Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.

Trying to treat TypeScript exactly like other languages is a recipe for disaster and bad code.
@MartinJohns
Well I do not see it like mimicking I see it more like strengthening OOP support in typescript.
In JavaScript you can have more parameters in function it is legal , but TS report error
with this option enabled it will do same for when there is less parameters.
Another benefit that callback function parameters can be better described
first is non optional and another are optional
In OOP programming scenario that I described above it will catch compile time error
and not in runtime .

@topce
Copy link
Author

topce commented May 30, 2023

@MartinJohns
Unfortunatly class is broken
you can check real example when I spotted this undesired behavior
#46881 (comment)

@MartinJohns
Copy link
Contributor

you can check real example when I spotted this undesired behavior
#46881 (comment)

If the author introduces breaking changes like this, then you're screwed no matter what. Even when the amount of arguments stays the same the arguments can have vastly different meanings. So what's next? The names of the arguments have to match? IMO this is an obscure corner case.

Honestly, your suggestion makes more sense as a linter rule, but not as part of the type system.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Declined The issue was declined as something which matches the TypeScript vision labels May 30, 2023
@RyanCavanaugh
Copy link
Member

We don't think this is a good idea, even as an option. This has been discussed to death in dozens of other threads and we don't need another iteration of that discussion here. #17868 (comment), #21868, etc etc.

@microsoft microsoft locked as resolved and limited conversation to collaborators May 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants