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

Support updating types based on mutations made to an object when passed to a function, out keyword #26213

Closed
4 tasks done
Olian04 opened this issue Aug 5, 2018 · 1 comment
Labels
Duplicate An existing issue was already created

Comments

@Olian04
Copy link

Olian04 commented Aug 5, 2018

Search Terms

typeguard for mutating function arguments

Suggestion

As it stands there's really no way of updating types based on mutations made to an object when passed to a function. E.g.

function Special(obj) {
  obj['foo'] = () => {};
}

const bar = {};
Special(bar);
bar.foo(); // ts-error, js-ok

However you can achieve something similar to the intended effect by using typeguards. E.g.

function Special<T>(obj: T): obj is T & { foo(): void; } {
  obj['foo'] = () => {};
  return true;
}

const bar = {};
if (!Special(bar)) throw 'Will never happen';
bar.foo(); // ts-ok, js-ok

But as you can see this is a rather hacky approach and it isn't exactly self-documenting.

I suggest that either:

a)

The type system should be able to infer that the type of an object has been updated through an object reference. This is relevant since this is how js works either way, no matter if ts acknowledges it or not

b)

Add another ts-keyword that suggests that the function will modify the type of a parameter, maybe we could use the out keyword from C#?

function Special(out obj) {
  obj['foo'] = () => {};
}

const bar = {};
Special(out bar);
bar.foo(); // ts-ok, js-ok

In the function scope an out argument should be considered a const value but not an immutable value.

function Fail(out obj) {
  obj = {}; // ts-error assigning to const
}

let obj = {};
Fail(out obj);

The out keyword is NOT optional.

function Fail(out obj) {}

let obj = {};
Fail(obj); // ts-error overload error, no overload takes a single "none out" argument

Use Cases

The first use case I've ran into, is when you are developing or using a library that decorates an object as part of the import. Using the out keyword would in these cases help making the code more self-documenting.

const foo = {};
require('someLibrary')(out foo);
foo.bar(); // ts-ok, js-ok

Checklist

My suggestion meets these guidelines:

  • I don't think it would be breaking This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)
@Olian04 Olian04 changed the title Support updating types based on mutations made to an object when passed to a function Support updating types based on mutations made to an object when passed to a function, out keyword Aug 5, 2018
@MartinJohns
Copy link
Contributor

Duplicate of #22865.

@Olian04 Olian04 closed this as completed Aug 5, 2018
@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants