Represent the types of function parameters that mutate inside the function.
See original GitHub issueIn JavaScript is possible to mutate objects inside functions. Right now, the following code in JavaScript:
function merge(x,y) {
Object.assign(x,y);
}
let x = {a: 1};
merge(x, {b: 2});
console.log(x.b);
Can’t be written in TypeScript without casting the type. There are a few options whose type definition is wrong in all scenarios I can think of (maybe I’m missing a better option):
Option 1
let x: {a: number, b: number} = {a: 1}; // Error, missing b
merge(x, {b: 2});
Option 2
let x: {a: number, b: number} = {a: 1, b: 2};
merge(x, {b: null});
// From here, x.b is not a number anymore, but you could do
let y: number= x.b;
Suggestion
There could be an extension to function parameter definition like the following:
// then keyword indicates that before it can be type A, and after it will be of type A&B.
function merge<A,B>(x: A then x2: A&B, y: B) {
Object.assign(x2,y);
}
let x: {a: number, b: number} = {a: 1, b: 2};
merge(x, {b: null});
// Here, type of x is {a: number, b: number} & {b: null}
x.b; // Type null
There, we indicate that whatever type was x before, now it is something different. The code above could be written in TypeScript as follows:
// then keyword indicates that before it can be type A, and after it will be of type A&B.
function merge<A,B>(x: A, y: B) {
Object.assign(x,y);
}
let x: {a: number, b: number} = {a: 1, b: 2};
merge(x, {b: null});
// Here, type of x is {a: number, b: number} & {b: null}
let xAfterMerge = x as {a: number, b: number} & {b: null};
// Since this line, x should not be used but xAfterMerge
xAfterMerge.b; // Type null
Another example
interface Before {
address: string;
}
interface After {
addr: string;
}
function map(userb: Before then usera: After) {
usera.addr = userb.address;
delete userb.address;
}
let u = {adress: "my street"};
map(u);
console.log(u.addr);
That could be syntax sugar for this:
interface Before {
address: string;
}
interface After {
addr: string;
}
function map(userb: any) {
userb.addr = userb.address;
delete userb.address;
}
let u = {adress: "my street"};
map(u);
console.log((u as After).addr);
Syntax
It could be something like:
identifier: type *then* identifier: type
With the identifiers being different, and with the types being mandatory an extension of Object.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:15
- Comments:8 (2 by maintainers)
Top Results From Across the Web
Correct Style for Python functions that mutate the argument
The first way: def change(array): array.append(4) change(array). is the most idiomatic way to do it. Generally, in python, we expect a ...
Read more >Functions - JavaScript - MDN Web Docs
Values can be passed to a function as parameters, and the function will return a value. In JavaScript, functions are first-class objects, ...
Read more >Mutate Function in R Programming - Video & Lesson Transcript
The mutate function takes as parameters the data set, the new variable name you will create, and the modification/mutation. Maybe you're just ...
Read more >6.1 mutate() | R for Graduate Students - Bookdown
This is a beginner's guide to coding in R.
Read more >Learning JavaScript functions and how you should use them
Function names and parameters are both considered variable names in JavaScript. ... to understand what we mean when we talk about reassignment and...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Just encountered this issue as well (typing stateful builders), rather disappointed to find out that it’s not really possible to do so without chaining the calls together. Does seem unlikely that this will be supported in TypeScript anytime soon as the original issue mutating function parameters is mostly covered by the
asserts
keyword. In case anyone’s searching for this, here’s the original code used as an example in this issue rewritten to type-check correctly:Another way of implementing this could be by adding a keyword that suggests that the function will modify the type of a parameter. We could borrow the
out
keyword from C#.In the function scope an
out
argument should be considered aconst
value but not an immutable value.The
out
keyword is NOT optional.We could then explicitly type the
out
argument with the previously purposedthen
keyword.I would just like to mention that you can achieve something close to this by “abusing” the typegurad feature.