Skip to content

add new compiler option #54441

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
wants to merge 3 commits into from
Closed

add new compiler option #54441

wants to merge 3 commits into from

Conversation

topce
Copy link

@topce topce commented May 29, 2023

implement new optional type checking flag veryStirctArity
by default false
when turn on more strictly check arity of methods
Actually add opportunity to fix https://github.com./microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters
so if new compilations flag is applied we would get error when try to assign function with fewer parameters to
function that take more parameters

This will help to catch some errors during compile time like explained in playground and in
comments bellow

Fixes #
#46881
although it is closed , maybe will this PR reconsider issue
First issue I open as a bug but probably should be improvement
I found this very useful improvement

playground link
https://www.typescriptlang.org/play?ts=5.1.0-beta#code/JYOwLgpgTgZghgYwgAgJLIN4FgBQzkAWwAFHAFzIDOYUoA5gDTIBGF1tIdAlBQG4D2wACYBuXAF9cuBABs4lSsgCCyYAFsADjIhqI4Remw4peQiXJUa9HsgHDMyAPSPkAOQDyyAKIAlH+59kAAlfL2QAd2AwAmQQCHDkGDk6ZGjoFGBFX38fXHx8aKh+BLiErygiqGIAIgBZCGj+IVj+MFVNbV1wCCEAOmrkAGpkOC4xU0ljHEnpOQVkACF2rR09MANMEzyzUjYrTiZWSw5GZAQ9k5s7ZqN81IIikvjvCv4quoaCJpa29RWuyB9AbDOBDFhjbYzaZbHBwZjsRBtWTyRRKEDqOAyTamOEIhBtNRwADWEAAyvwAK4gITESiU6kXax8QSiEz4NT8XgQYhXFnYu4IfggOnaXoyfh0Go+fhwNT0e4oCBwKDRXpq6oQiYSEzI+YAEQlyAgAA9INTUejCVjbshCSTyVSaVwHM43J5sgFgqEIlEYqVEskFVAMlk-AFtvhBcL+KLxZLqgB1fj8GAAQmQSZTqY143wkyhUeoyCEhoAvLFngbJZqS3RenayfSnSInC5M2mM8m07ha-XOdyxq3kNLZfK0kblaq1SZcTREWc5ooAFrAARgUAAK1BNtnUHnDYd1NpTYA-IzOLzhONthyuTzmfYbZGhSKIGKJVKZXLOAqJyqCGq-Sanm2pTLqigAAryEapp6EIy6rq0m6gvytrEo2jo8i6LgeN4YaBCEPhhJE0QVgkSRwCkzAQAgcAUpQKB0o6qiKPwGjriAmIRmcL4xm+cY1O26ZCTmkKgbgQA

veryStirctArity
by default false
when turn on more strictly check arity of methods
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label May 29, 2023
@topce
Copy link
Author

topce commented May 29, 2023

@topce please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

Contribution License Agreement

This Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”), and conveys certain license rights to Microsoft Corporation and its affiliates (“Microsoft”) for Your contributions to Microsoft open source projects. This Agreement is effective as of the latest signature date below.

  1. Definitions.
    “Code” means the computer software code, whether in human-readable or machine-executable form,
    that is delivered by You to Microsoft under this Agreement.
    “Project” means any of the projects owned or managed by Microsoft and offered under a license
    approved by the Open Source Initiative (www.opensource.org).
    “Submit” is the act of uploading, submitting, transmitting, or distributing code or other content to any
    Project, including but not limited to communication on electronic mailing lists, source code control
    systems, and issue tracking systems that are managed by, or on behalf of, the Project for the purpose of
    discussing and improving that Project, but excluding communication that is conspicuously marked or
    otherwise designated in writing by You as “Not a Submission.”
    “Submission” means the Code and any other copyrightable material Submitted by You, including any
    associated comments and documentation.
  2. Your Submission. You must agree to the terms of this Agreement before making a Submission to any
    Project. This Agreement covers any and all Submissions that You, now or in the future (except as
    described in Section 4 below), Submit to any Project.
  3. Originality of Work. You represent that each of Your Submissions is entirely Your original work.
    Should You wish to Submit materials that are not Your original work, You may Submit them separately
    to the Project if You (a) retain all copyright and license information that was in the materials as You
    received them, (b) in the description accompanying Your Submission, include the phrase “Submission
    containing materials of a third party:” followed by the names of the third party and any licenses or other
    restrictions of which You are aware, and (c) follow any other instructions in the Project’s written
    guidelines concerning Submissions.
  4. Your Employer. References to “employer” in this Agreement include Your employer or anyone else
    for whom You are acting in making Your Submission, e.g. as a contractor, vendor, or agent. If Your
    Submission is made in the course of Your work for an employer or Your employer has intellectual
    property rights in Your Submission by contract or applicable law, You must secure permission from Your
    employer to make the Submission before signing this Agreement. In that case, the term “You” in this
    Agreement will refer to You and the employer collectively. If You change employers in the future and
    desire to Submit additional Submissions for the new employer, then You agree to sign a new Agreement
    and secure permission from the new employer before Submitting those Submissions.
  5. Licenses.
  • Copyright License. You grant Microsoft, and those who receive the Submission directly or
    indirectly from Microsoft, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license in the
    Submission to reproduce, prepare derivative works of, publicly display, publicly perform, and distribute
    the Submission and such derivative works, and to sublicense any or all of the foregoing rights to third
    parties.
  • Patent License. You grant Microsoft, and those who receive the Submission directly or
    indirectly from Microsoft, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license under
    Your patent claims that are necessarily infringed by the Submission or the combination of the
    Submission with the Project to which it was Submitted to make, have made, use, offer to sell, sell and
    import or otherwise dispose of the Submission alone or with the Project.
  • Other Rights Reserved. Each party reserves all rights not expressly granted in this Agreement.
    No additional licenses or rights whatsoever (including, without limitation, any implied licenses) are
    granted by implication, exhaustion, estoppel or otherwise.
  1. Representations and Warranties. You represent that You are legally entitled to grant the above
    licenses. You represent that each of Your Submissions is entirely Your original work (except as You may
    have disclosed under Section 3). You represent that You have secured permission from Your employer to
    make the Submission in cases where Your Submission is made in the course of Your work for Your
    employer or Your employer has intellectual property rights in Your Submission by contract or applicable
    law. If You are signing this Agreement on behalf of Your employer, You represent and warrant that You
    have the necessary authority to bind the listed employer to the obligations contained in this Agreement.
    You are not expected to provide support for Your Submission, unless You choose to do so. UNLESS
    REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, AND EXCEPT FOR THE WARRANTIES
    EXPRESSLY STATED IN SECTIONS 3, 4, AND 6, THE SUBMISSION PROVIDED UNDER THIS AGREEMENT IS
    PROVIDED WITHOUT WARRANTY OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF
    NONINFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
  2. Notice to Microsoft. You agree to notify Microsoft in writing of any facts or circumstances of which
    You later become aware that would make Your representations in this Agreement inaccurate in any
    respect.
  3. Information about Submissions. You agree that contributions to Projects and information about
    contributions may be maintained indefinitely and disclosed publicly, including Your name and other
    information that You submit with Your Submission.
  4. Governing Law/Jurisdiction. This Agreement is governed by the laws of the State of Washington, and
    the parties consent to exclusive jurisdiction and venue in the federal courts sitting in King County,
    Washington, unless no federal subject matter jurisdiction exists, in which case the parties consent to
    exclusive jurisdiction and venue in the Superior Court of King County, Washington. The parties waive all
    defenses of lack of personal jurisdiction and forum non-conveniens.
  5. Entire Agreement/Assignment. This Agreement is the entire agreement between the parties, and
    supersedes any and all prior agreements, understandings or communications, written or oral, between
    the parties relating to the subject matter hereof. This Agreement may be assigned by Microsoft.

@microsoft-github-policy-service agree

@xiBread
Copy link

xiBread commented May 29, 2023

The issue was closed for a reason. It's not a bug. It does not need "fixing."

@topce
Copy link
Author

topce commented May 29, 2023

The issue was closed for a reason. It's not a bug. It does not need "fixing."

Well you are right it is not a bug it is improvement ;-)

@topce
Copy link
Author

topce commented May 30, 2023

Code bellow with produce errors with new flag

function mymap<T, U>(arr: T[], callback: (value: T, index: number, array: T[]) => U): U[] {
  const result: U[] = [];

  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i, arr));
  }

  return result;
}

const numbers = [1, 2, 3, 4, 5];

const doubled = mymap(numbers, (value) => value * 2); // error with new flag veryStrictArity
console.log(doubled); // Output: [2, 4, 6, 8, 10]

const squared = mymap(numbers, (value) => value * value); // error with new flag veryStrictArity
console.log(squared); // Output: [1, 4, 9, 16, 25]

@topce
Copy link
Author

topce commented May 30, 2023

but if we define function more strict there will be no error in code bellow
function mymap<T, U>(arr: T[], callback: (value: T, index?: number, array?: T[]) => U): U[] {
so code is more type safe

function mymap<T, U>(arr: T[], callback: (value: T, index?: number, array?: T[]) => U): U[] {
  const result: U[] = [];

  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i, arr));
  }

  return result;
}

const numbers = [1, 2, 3, 4, 5];

const doubled = mymap(numbers, (value) => value * 2); // no error with new flag veryStrictArity
console.log(doubled); // Output: [2, 4, 6, 8, 10]

const squared = mymap(numbers, (value) => value * value); // no error with new flag veryStrictArity
console.log(squared); // Output: [1, 4, 9, 16, 25]

@xiBread
Copy link

xiBread commented May 30, 2023

How is this an improvement? Your type states a parameter could be undefined even though it never can be, and if I want to use the index, I have to do unnecessary optional chaining, undefined check, or non null assertion.

@topce
Copy link
Author

topce commented May 30, 2023

You can see in my example above that you do not need to do any of this if function is defined more strict
function mymap<T, U>(arr: T[], callback: (value: T, index?: number, array?: T[]) => U): U[] {
code will work because compiler knows that index and array are optional parameter
however if function is defined like bellow
function mymap<T, U>(arr: T[], callback: (value: T, index: number, array: T[]) => U): U[] {
with a new flag you will see error
So that why in my opinion it is big improvement of current state
If somebody opt to turn on flag he will get more type checking

@topce
Copy link
Author

topce commented May 30, 2023

with new flag veryStrictArity
example from https://github.com./Microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters
would give compile time error like some people including myself expect

function handler(arg: string) {
    // ....
}

function doSomething(callback: (arg1: string, arg2: number) => void) {
    callback('hello', 42);
}

// Expected error because 'doSomething' wants a callback of
// 2 parameters, but 'handler' only accepts 1
doSomething(handler);

@topce
Copy link
Author

topce commented May 30, 2023

error TS2345: Argument of type '(arg: string) => void' is not assignable to parameter of type '(arg1: string, arg2: number) => void'.
Target signature provides too many arguments. Expected 1 or more, but got 2.

11 doSomething(handler);
~~~~~~~

@topce
Copy link
Author

topce commented May 30, 2023

with new flag veryStrictArity
another example from https://github.com./Microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters
would give compile time error

let items = [1, 2, 3];
items.forEach(arg => console.log(arg)); // error like expected

type Callback<T> = (value: T, index?: number, array?: T[]) => void;

interface Array<T> {
  myForEach(callback: Callback<T>): void;
}

Array.prototype.myForEach = function <T>(callback: Callback<T>): void {
  for (let i = 0; i < this.length; i++) {
    callback(this[i], i, this);
  }
};

items.myForEach(arg => console.log(arg)); // no error because index and array are optional parameters

@topce
Copy link
Author

topce commented May 30, 2023

and finally on the last point of https://github.com./Microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters
they was right :
which would be "fixed", but not made any more correct, by adding a parameter:
[1, 2, 3].forEach(x => console.log("just counting"));
// OK, but doesn't do anything different at all
I would write it like
[1, 2, 3].forEach(_x => console.log("just counting"));
underscore specify unused parameter
Not ideal but in my opinion small price to pay for bigger benefits,
and increased type safety .

@topce
Copy link
Author

topce commented May 30, 2023

so basically with this flag turn on
Why are functions with fewer parameters assignable to functions that take more parameters?
should be
If you want functions with fewer parameters not to be assignable to functions that take more parameters
use veryStrictArity compiler flag

@topce
Copy link
Author

topce commented May 30, 2023

Create new issue #54449 so we can discuss it.
This PR fix this issue

@RyanCavanaugh
Copy link
Member

For clarity, we are unable to review pull requests not addressing approved feature work

@topce
Copy link
Author

topce commented May 31, 2023

Dear @RyanCavanaugh,

I wanted to share my thoughts regarding the closed PR. I believe it was closed rather quickly. Upon reviewing the comments, I noticed they were from 2017 and 2018. I believe this PR could address both those issues, as well as other related concerns, as you mentioned. You can find more details about it in the following GitHub issues:

#17868 by @inad9300
#21868 by @canonic-epicure
It's worth considering that TypeScript has evolved significantly since those comments were made. Therefore, it may be beneficial to reconsider this PR.

Regarding your comment (#17868 (comment)) and a similar comment by @xiBread, I wanted to highlight that it doesn't directly affect this PR. As I explained, it depends on how the type of map, forEach, filter, or sort is defined. To illustrate this, here's an example:

type SelfOrPartial<T> = T | Partial<T>;
type Callback<T> = (value: T, index: number, array: T[]) => void;
interface Array<T> {
  forEach(callbackfn: SelfOrPartial<Callback<T>>): void;
}
const items = [1, 2, 3];
items.forEach(arg => console.log(arg));
items.forEach(() => console.log("just counting"));

This code compiles without any issues, even when the veryStrictArity flag is activated.

Perhaps it would be beneficial to seek the opinion of @ahejlsberg as well. Given his extensive experience in both OOP and functional programming, he might have a better understanding of this PR and its implications.

Thank you for considering my input.

@RyanCavanaugh
Copy link
Member

I think you're under the impression that we just haven't considered this before. We have considered it many, many times.

@topce
Copy link
Author

topce commented May 31, 2023

Thank you for your response. I apologize for any misunderstanding. Could you kindly explain the potential drawbacks of implementing this as an optional parameter? I have read the provided information but am still trying to fully understand the reasoning behind the decision. I mainly see the positive aspects of this PR and its potential benefits. Your clarification would be greatly appreciated.

@topce
Copy link
Author

topce commented Jun 1, 2023

@RyanCavanaugh,

I wanted to bring to your attention that this PR also addresses an issue raised by @jesseschalken back in 2016 (#13043). Additionally, it seems that the problem I am currently facing is similar to the one encountered by Google, as mentioned in this comment by mbrobst (#13043 (comment)). I also came across another related issue raised by @ORESoftware (#20274).

While I understand that the TypeScript team may not consider this as a high-priority matter, I believe that implementing it as an optional flag could greatly enhance TypeScript's object-oriented programming capabilities. Many other developers, including myself, see significant value in this proposed enhancement. I still find myself struggling to comprehend the underlying concerns or objections to this PR.

I sincerely appreciate your time and consideration. Thank you for allowing me to express my perspective.

@RyanCavanaugh
Copy link
Member

What you're proposing here is that function subtyping not uniformly act like function subtyping -- that a bare function you can pass to forEach have different rules than a function that exists as part of a class method being compared to an implements clause. This lack of consistency would have many downstream effects -- if you say that

class A implements B { /* ... */ }

has different logic than

const x: B = new A();

then there should be some strong theoretical justification for doing this, since that sort of check is the entire reason to have an implements clause in the first place.

But there isn't a strong theoretical justification, because we know that in JavaScript, excess arguments do not create any runtime problems. We also know from inspection that these two functions do not have different correctness:

// zero parameters
function x1() {
  return 0;
}
// one unused parameter
function x2(n: number) {
  return 0;
}

So trying to say that it's correct for x2 to implement some contract, but not x1, doesn't make any sense. x1 is a subtype of x2 according to any reasonable definition of JavaScript function rules you might have. If you want to claim that class methods should have different rules than functions, that's just a weird asymmetry that we have to explain everywhere and doesn't actually provide any concrete value in terms of creating a more consistent and predictable type system.

@topce
Copy link
Author

topce commented Jun 2, 2023

@RyanCavanaugh
Thank you for your patience!

My original problem was this one
#46881 (comment).
I thought that TypeScript compiler should warn me
I fix this issue in this PR by adding new compiler flag when it is turn on
I got compile time error
But after I realized, thanks to you
that this will solve lot of other issues
for example one line code bellow does not compile (expected)
const some : ((arg: string) => boolean) = () => true;
but this one bellow compile (expected) because arg is optional parameter arg?
const some : ((arg?: string) => boolean) = () => true;

So when this parameter is turn on TypeScript is more powerful
and made distinction between
two signatures
((arg: string) => boolean)
and
((arg?: string) => boolean)
Otherwise it does not make distinction when flag is not turn on.

I think it is good improvement.
"What you're proposing here is that function subtyping not uniformly act like function subtyping -- that a bare function you can pass to forEach have different rules than a function that exists as part of a class method being compared to an implements clause"
Not sure I understand well (study compilers in university 30 year ago),
but I do not treat function that I can pass to forEach any differently than function that exists
as part of class I treat them same way.
Some people complain that with veryStrictArrity on
they will need to do more checking
I replied it depends how for each callback function is defined
if it is defined like this

type Callback<T> = (value: T, index: number, array: T[]) => void;
// indeed code bellow will not compile 
const items = [1, 2, 3];
items.forEach(arg => console.log(arg)); // error 
items.forEach(() => console.log("just counting")); //error

with a new flag

but if it is forEach callback redefine like this

type SelfOrPartial<T> = T | Partial<T>;
type Callback<T> = (value: T, index: number, array: T[]) => void;
interface Array<T> {
  forEach(callbackfn: SelfOrPartial<Callback<T>>): void;
}
// code bellow will still work
const items = [1, 2, 3];
items.forEach(arg => console.log(arg)); //no errors
items.forEach(() => console.log("just counting")); // no errors

it all depends of type definition.

@topce
Copy link
Author

topce commented Jun 2, 2023

error message:
test.ts:18:7 - error TS2322: Type '() => true' is not assignable to type '(arg: string) => boolean'.
Target signature provides too many arguments. Expected 0 or more, but got 1.

18 const some : ((arg: string) => boolean) = () => true;
~~~~

@topce
Copy link
Author

topce commented Jun 2, 2023

@RyanCavanaugh
regarding second point agree with you

// zero parameters
function x1() {
  return 0;
}
// one unused parameter
function x2(n: number) {
  return 0;
}

Indeed if you declare function x2 as bellow with optional parameter
even when new proposed flag is active your code should compile

// zero parameters
function x1() {
  return 0;
}
// one unused parameter
function x2(n?: number) {
  return 0;
}

but if you specify veryStrictArity true
and in x2 you do not have optional parameter
you will get compile time error

if veryStrictArity is false (default option) it will still be compiled without error

So I do not understand what is still problem with this PR?

I see this PR similar like when your team fix null/undefined problem
with this PR we introduce option to have more strict function definition
and also make TS more OOP friendly language

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jun 2, 2023

// one unused parameter
function x2(n?: number) {

You have the definition of optionality backwards. This is covered in the FAQ

At this point we are well into the middle of territory that has been trod many times over in past discussions, and I really ask that you read them all comprehensively before making points that have been covered before. I am not having a 12th iteration of a conversation about what the definition of parameter optionality is.

@topce
Copy link
Author

topce commented Jun 3, 2023

So, in fact, there are dual meanings of the optional parameter: one when describing functions and another when describing callbacks. I personally find this confusing, and that's why I proposed this PR to address the issue. Allow me to share some comments from the FAQ:

function handler(arg: string) {
    // ....
}

function doSomething(callback: (arg1: string, arg2: number) => void) {
    callback('hello', 42);
}

// Expected error because 'doSomething' wants a callback of
// 2 parameters, but 'handler' only accepts 1
doSomething(handler);

I expected the same behavior, and with this PR, one could enable a flag to receive a warning. If the intention was to avoid the warning, the function should be defined like this:

function doSomething(callback: (arg1: string, arg2?: number) => void) {
    callback('hello', 42);
}

Regarding forEach, as I explained in the example above, it depends on how the callback is defined.

// Invoke the provided function with 0 or 1 argument
function maybeCallWithArg(callback: (x?: number) => void) {
    if (Math.random() > 0.5) {
        callback();
    } else {
        callback(42);
    }
}

The above code compiles with the veryStrictArity option turned on. I fail to understand why we have two meanings of optional parameters and what is the purpose of the second meaning.

In the FAQ, there is also a statement that says: "There is currently not a way in TypeScript to indicate that a callback parameter must be present. Note that this sort of enforcement wouldn't ever directly fix a bug." However, with the veryStrictArity option, this is now possible.

Thank you for your time! I won't bother you any longer. I will use my fork with the new flag and publish it on npm. This will allow me to catch some errors at compile time, which is not possible with the current version.

Once again, thank you for your assistance!

@topce
Copy link
Author

topce commented Jun 26, 2023

@fatcerberus,

In reference to this comment,
If you wish to avoid errors, one way could be to override the type definition for the map callback as shown below:

type JavaScriptCallback<
  T extends (...args: any) => any,
  P = Parameters<T>
> = P extends [...infer Rest, infer _Last]
  ? ((...args: Rest) => ReturnType<T>) | JavaScriptCallback<T, Rest>
  : T;

interface Array<T> {
  map<U>(
    callbackfn: JavaScriptCallback<(value: T, index: number, array: T[]) => U>,
    thisArg?: any
  ): U[];
}
or not to use veryStrictArity option at all

@topce
Copy link
Author

topce commented Jun 26, 2023

@RyanCavanaugh,

I would like to respectfully voice a different perspective in response to your comment here. I've actually published a fork of TypeScript available here, which has this feature permanently enabled. I've found it to be greatly beneficial in my work.

In addition, I recently stumbled upon an older blog post here and the ensuing discussion here. Notably, the code snippet ["1","2","3"].map(parseInt); will not compile with @topce/typescript but does with the standard TypeScript. However, if the JavaScriptCallback that I mentioned above is applied, it will compile with @topce/typescript as well. This enables developers to choose whether they prefer stricter type checks or not.

I want to take this opportunity to express my gratitude for your help and insights on this matter!

One of the wonderful aspects of open-source projects is the ability to fork and publish if the original version doesn't entirely meet one's requirements. While my preference would have been for my PR's to be accepted, I'm content with using my own version until a more satisfactory solution that addresses this issue is introduced.

@fatcerberus
Copy link

fatcerberus commented Jun 26, 2023

So, in fact, there are dual meanings of the optional parameter

No, it always means the same thing - the caller of that function may omit the argument (which means you, as the person implementing it, have to deal with the possibility of the value being undefined). You’re just looking at the caller/callee relationship from the opposite direction when passing a callback, so it appears inconsistent, but it’s not.

@topce
Copy link
Author

topce commented Jun 26, 2023

So, in fact, there are dual meanings of the optional parameter

No, it always means the same thing - the caller of that function may omit the argument (which means you, as the person implementing it, have to deal with the possibility of the value being undefined). You’re just looking at the caller/callee relationship from the opposite direction when passing a callback, so it appears inconsistent, but it’s not.

@fatcerberus Thank you for clarification, however it is still contra intuitive to me,
for me it would be more logical to always look from same direction.

@fatcerberus
Copy link

for me it would be more logical to always look from same direction.

By analogy—you’re basically arguing that I should always walk up to you with my back turned just so that my right hand appears on your right, which is not at all a logical request.

@topce
Copy link
Author

topce commented Jun 26, 2023

for me it would be more logical to always look from same direction.

By analogy—you’re basically arguing that I should always walk up to you with my back turned just so that my right hand appears on your right, which is not at all a logical request.

IMHO bad analogy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants