Description
Search Terms
mutation, reference parameter mutation, delete, old js assignment.
Feature:
The ability to support in and out type formats for generics and output guard formats,
which would allow one to handle all inline mutations of type with assignment in js assignment and
function like delete, which mutate the type keys. Typically many function mutate the structure, in which they don't use the copy on write principle or c++ const protection as not available.
This is simple proposal to accommodate all the required cases:
This is a suggestion, the final form of this may differer.
interface A {
a : Date;
b : number;
c : string;
d : boolean;
}
const record : A = {
a : new Date(),
b : 1,
c : "str",
d : true
}
delete record.b;
// Shouldn't be accessible anymore.
record.b = 5;
// Example function signature as of sorts.
function deletefFun<This extends Record<string, any>, Key extends keyof This>(object : This, key : Key) : undefined | Key
{
if(object[key])
{
object[key] = undefined; //deleted
}
else
{
return key;
}
}
Generic Type support for Reference in/out
Require function signature to support type in and out, where the structure is internally mutated ( reference parameter) Currently ts assume that all input params will not be mutated any future.
This couple with a implicitly guard functionality for mutable ref tables, would ensure
that there can be no errors in ones coding, or require work around, everything should just work.
If inline mutation of a type is support then the output format could be compute automatically.
function deletefFun<{in:This extends Record<string, any>,out:PickInverse<This,key>}, Key extends keyof This>(object : This, key : Key) : undefined | Key
{
if(object[key])
{
object[key] = undefined; //delete
}
else
{
return key;
}
}
Generic Type with Reference in/out and implicit Gard
This would be a function with a simple implicit boolean guard format, which format that should be compatible with union kind.which would then support multiple implicit type guards.
function deleteFunGaud<{
in: This extends Record<string, any>,
gaurd: {
undefined:PickInverse<This,key>,
[Key]:Key
}
,Key extends keyof This>(object : This, key : Key) : undefined | Key
{
}
Yes, in this example on the mutation is required, if because one is able to ensure that the key exists, however, if this statement could fail for any other reason or throw and error, then the type guad, would work perfectly. some underlying memory allocation failed. Some thought into the use with catch, statement to know the final mutated form, before that throw, were should be a subset of existing fields, which have not been mutated in the try, as we don't know the state until runtime and guards should need to be used for all those parameters in the catch statement, maybe a shorthand inline guard, would be good if go the catch support route too.
Examples use of functions In/Out and Guards
Exmaple 1:
deleteFunGaud(record, 'b') // results is undefined | 'b'
record.b // is of type Error('Implicit guard check is missing, not can't be know, without runtime check')
// or
record = // This should reset the reference, back to a form that match existing type prior to mutation.
Example 2:
if (deleteFunGuad(record, 'b'))
{
record.b // undefined and is not available, it has been removed.
}
else
{
record.b // Is defined, because delete failed.
}
This also becomes a problem when one wants to mutate and object in old school style
style, one needs to use the spread operator or Object.assign(..) to mutate the type,
with copy on write principles alot of existing code mutates the object structure after a pull from a database. Most of the code, must now be formatted in the copy on write principle.
This is true for most all code, were results are returned and additional information is tack onto the existing database return structure. It would be nice, if index operator could automatically mutate the types, when executed in a block(body) of code.
InlineMutation
function fun(paramA : A){}
record.p : string = 'p';
record.z = 'z' as string;
fun(record) // error type mismatches, as it has been mutated.
fun({} as A) // Good
record = {} as A // fails, type mismatches as it has been mutated.
Other Related Issues:
Checklist
My suggestion meets these guidelines:
- 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)