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

dtypeof = typeof, but ignores all inferred types from assignments' that reference this object keys. More concise & constant behaviour #24517

Closed
4 tasks done
wesleyolis opened this issue May 31, 2018 · 7 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision

Comments

@wesleyolis
Copy link

wesleyolis commented May 31, 2018

dtypeof is suggested new keyword that performs a semantically similar operation as typeof, however, ignores all inferred types determined from assignment which reference the object keys that typeof operates on.

typeof allows one to do many advanced and great things with the types engine, but they are subject to inferred types constraints, that reference the objects keys, were an inferred alternative manual type constraint, then overides the typeof that we are really interested in.

Generally speaking this is only a problem when someone wants to reference an object upon, which one performed the typeof operation on, as it then changes the typeof signature, every where potentially in ways that are not ideally to the behaviour we were looking for, which should be constant and not changed indirectly by someone referencing a key with an assignment operator that has a type constraint, which then infers a different a type, changing the results of the typeof operator, which could be see as unintentional and by mistake or break existing dependancies.

This typically I would imagine that one would want the more predictable behaviour of the function type of under a different name dtypeof

UseCases And Examples Behaviours

Typically usage

const object  = {
a : 23,
b : 'sdfsfd',
c: true,
d: false
}

type TObject = typeof object

// typically this be somthing more abstract like
type TypeGeneric<T> = ....
type ATObject = TypeGeneric<typeof object>

// TObject types look like this.

TObject = {
a : number,
b : string,
c : boolean,
d : boolean
}

Current undesired behaviour

const overideString : string = object.c; // inferred type by reference
const overideNumber : number = object.b; // inferred type by reference

const object  = {
a : 23,
b : 'sdfsfd',
c: true,
d: false
}

type TObject = typeof object
// TObject types look like this, due to the inferred type by reference, or result in a type 'any' if their no implicit conversions
TObject = {
a : number,
b : number,
c : string,
d : boolean
}

Wanted constant behaviour with using dtypeof

const overideString : string = object.c; // inferred type by reference
const overideNumber : number = object.b; // inferred type by reference

const object  = {
a : 23,
b : 'sdfsfd',
c: true,
d: false
}

type TObject = dtypeof object
// TObject types look like this, all inferred type by reference are ignored.
TObject = {
a : number,
b : string,
c : boolean,
d : boolean
}

Wanted constant behaviour with using dtypeof, even with type constraint

Structural constrains to constrain setup of objects or return of function method type signatures
were dtype is a type to be determined at runtime by type inference. We current use this pattern to achieve some really cool dynamic types using generics, instead of having to have preprocesses that generate the types for you.

type HasStructure = {s :dtype, DType : 'T' | 'F'}
type TStructuralObj = {
 {
a : HasStructure,
b : HasStructure,
c : HasStructure,
d : HasStructure
}


const overideString : string = object.c.s; // inferred type by reference, should be ignored
const overideNumber : number = object.b.s; // inferred type by reference, should be ignored

const object : TStructuralObj = {
a : {s : 23, DType:'T'},
b : {s:'sdfsfd', DType:'F'},
c: {s:true, DType:'F'},
d: {s:false, DType:'T'}
}

type TObject = dtypeof object
// TObject types look like this, all inferred type by inferred references are ignored.
TObject = {
a : {s:number,'T'},
b : {s:string,'F'},
c : {s:boolean,'F'},
d : {s:boolean,'T'}
}

Recursive type entry evaluation, for different use case and feature to be cognisant of when implemented this feature improvement of dtype.

What be even more cool, is if typescript support Generic recursion, because then could pose a different set of types constraints on const object initialisation that what we get out.

This can partially be done with classes, however, the compiler doesn't constrain the class definition by the defaulted T ='T' for each definition or a variable declaration that use T, so that when assigned in the class definition, it must match the evaluated type specified by T ='T'.
If this could be done it would be really great too.

const object : TypeGenericObject<T ='F'> =
{
f : as B<A>
}
typeof TObject = dtypeof object<'T'>

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)
@wesleyolis wesleyolis changed the title Dypeof = typeof, but ignores all inferred types that reference this object keys, with a variable assignment that declare the t ypewhere by a variable declarations with type constraints dtypeof = typeof, but ignores all inferred types from assignments' that reference this object keys May 31, 2018
@wesleyolis wesleyolis changed the title dtypeof = typeof, but ignores all inferred types from assignments' that reference this object keys dtypeof = typeof, but ignores all inferred types from assignments' that reference this object keys. More concise & constant behaviour May 31, 2018
@jcalz
Copy link
Contributor

jcalz commented May 31, 2018

I can't really understand what you're saying. Furthermore, I can't reproduce the "current undesired behavior". This is what happens:

const overideString: string = object.c; // error
const overideNumber: number = object.b; // error

var object = {
  a: 23,
  b: 'sdfsfd',
  c: true,
  d: false
}

type TObject = typeof object
/*
type TObject = {
  a: number,
  b: string,
  c: boolean,
  d: boolean
}
*/

View in Playground

You can't mutate the type of a value from string to number, or vice versa, so your "override" lines are errors. The type TObject is what you want it to be. What is the issue again? 😕

@mhegazy mhegazy added the Declined The issue was declined as something which matches the TypeScript vision label May 31, 2018
@mhegazy
Copy link
Contributor

mhegazy commented May 31, 2018

In addition, the compiler can not really tease out sources of property declarations from a type after it is formed.

@wesleyolis
Copy link
Author

wesleyolis commented Jun 10, 2018

@jcalz, Sorry if this was a miss understanding, this wasn't meant to be taken so literally. It was merely to act as a simplified example to communicate the behaviour we have observed, in our much more complicated type manipulations, we are performing. Clearly if taken literally then you are 100% right.
Because I can't really share our work that we have done right now with you publicly just yet. This example was the best I could do. I can potentially from my experience only offer the following rebuffel,
please ask the person who is responsible and who has written to AST processing for typeof operator to re-read thought his code interrogating, it for the behaviour describe above, if discovered reconsider this issues. I can also potentially do it, just going to take me longer than the person who wrote that section of the compiler. I have have pulled the typescript repository on to my local machine and started to poke around to get up to speed with things for myself.. For reason mentioned here: In this post

Lets say our work around for this behaviour to stop it happening was to simply extract our typeof operator usage into a single file and then export them. Because then the indirect reference behaviour which could change a type definition is contained to the same file in which typeof is used.
For me extract of typeof usage to another file for now, provides' me with enough assurance, that this mistake can't happen in a much larger file.

I hope that this finds you in the best interest of the ecosystem.

@jcalz
Copy link
Contributor

jcalz commented Jun 10, 2018

I am not really affiliated with the language maintainers and have no special influence with those who are, so I doubt it would help much if I were to ask someone to investigate. Furthermore I still don't understand the issue, nor do I understand how to interpret code in a non-literal way (maybe there's a --figurative compiler flag?). Hopefully someone who understands and who is in a position to act will address your issue. Good luck.

@wesleyolis
Copy link
Author

Then how are you suppose to vet issues like this? Surely you should have a procedure on how to handle task and esculate this issue, until it finds it way up the hierarchy of knowledge to someone who is capable of dealing with this level of request... Or weather the request should become a TC39 issues and handle by one of the comity/community members who implemented the features...??

@jcalz
Copy link
Contributor

jcalz commented Jun 11, 2018

I am a frequent shopper at this grocery store. You are another customer having a problem with an item you purchased. I wanted to be helpful; maybe I could point you toward the aisle that contains a more acceptable product. But unfortunately I don't understand what your problem is: you left the relevant item at home and your verbal description doesn't make sense to me. At this point I say I don't think I know how to help you and try to continue my shopping. But you start following me. I tell you: "I don't work here." But you are upset about your item and my lack of helpfulness, and keep following and complaining about the store. Maybe you think I secretly do work here? Or that I should have done more as a fellow customer in the interest of consumer solidarity? I don't know, but I'm beginning to worry. I walk faster, calling back to you over my shoulder: "Sorry, but I really don't work here and I don't think I can help. Good luck!" I turn a corner, then leave my shopping cart at the end of the aisle, and quickly hide behind a display case so you won't see me if you keep trying to follow. It's paranoid, I know, but I can't help it at this point. Okay, I need to just calm down and move on with my day. Besides, you're not really following me, right? Fine, great. Still, instead of confidently striding back to my cart, I cautiously peer out past the edge of my display case to see if you're waiting for me. What do I see?

@DanielRosenwasser
Copy link
Member

Since I don't think this conversation is going to become constructive, I'm going to lock this issue.

@microsoft microsoft locked and limited conversation to collaborators Jun 11, 2018
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
Projects
None yet
Development

No branches or pull requests

4 participants