You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Should/could typeguarding work on arrays/length #10272
// --strictNullChecksletargs=process.argv.slice(2)// type: string[]lettest1=args[Number.MAX_VALUE]// type: 'string' but should it be 'string | undefined' ?if(args.length>0){lettest2=args.shift()// Type: 'string | undefined' - but should it be 'string' ?}
Marin Marinov (@gcnew) Thanks for the explanation, but then shouldn't accessing sparse arrays and having --strictNullChecks on - always return T | undefined
@wallverb Yes, well and truly. It was done for convenience as explained by the reply to #7140 (comment)
PS: To play devil's advocate, I guess the return type of shift() is written as T | undefined to accommodate for shifting an empty array, no so much about the sparse case. In this sense you are right, but it would be very hard to create a generic solution that takes into account all the hidden, intricate knowledge of an objects state and apply it to it's methods.
functionisShiftable<T>(arr: T[]): arr is Array<T>&{shift(): T;}{return!!arr.length;}constarr: number[]=[5];if(isShiftable(arr)){constx=arr.shift();// x is of type `number`}
functionisNotEmpty<T>(arr: T[]): arr is Array<T>&{pop(): T;}{returnarr.length>0;}functiondoSomething(){conststack: Vertex[]=[]constgroups: string[]=[]// put some things on the stackwhile(isNotEmpty(stack)){constv=stack.pop()// v is still typed as Vertex | undefinedgroups.push(v.id)// [ts] Object is possibly 'undefined'}}
did I miss something?
(tried this with typescript 2.0.3 and 2.1.0-dev.20160924)
Update: changed the order of the return type def like so:
functionisNotEmpty<T>(arr: T[]): arr is {pop(): T;}&Array<T>
and it works as desired. Is the type intersection operator not commutative?
David Manning (@dlmanning) You are right, the suggested fix is the the way to go. It should be noted though that this type guard is a hack - I just found that it worked. About the type intersection operator I don't think there is a notion of commutativity, I suspect it's just the compiler picking the first matching declaration.
Activity
gcnew commentedon Aug 11, 2016
Strictly speaking - no. It doesn't guard against sparse arrays, e.g:
Then again, the true type of indexing is also
T | undefined.normalser commentedon Aug 11, 2016
Marin Marinov (@gcnew) Thanks for the explanation, but then shouldn't accessing sparse arrays and having
--strictNullCheckson - always returnT | undefinedargs[Number.MAX_VALUE] // type: 'string'gcnew commentedon Aug 11, 2016
@wallverb Yes, well and truly. It was done for convenience as explained by the reply to #7140 (comment)
PS: To play devil's advocate, I guess the return type of
shift()is written asT | undefinedto accommodate for shifting an empty array, no so much about the sparse case. In this sense you are right, but it would be very hard to create a generic solution that takes into account all the hidden, intricate knowledge of an objects state and apply it to it's methods.normalser commentedon Aug 11, 2016
wow, interesting, thank you so much for finding that comment for me. I wish such knowledge was more easily accessible/findable :)
gcnew commentedon Aug 11, 2016
BTW: as a workaround this works:
dlmanning commentedon Sep 25, 2016
This workaround is not working for me.
did I miss something?
(tried this with typescript 2.0.3 and 2.1.0-dev.20160924)
Update: changed the order of the return type def like so:
and it works as desired. Is the type intersection operator not commutative?
gcnew commentedon Sep 25, 2016
David Manning (@dlmanning) You are right, the suggested fix is the the way to go. It should be noted though that this type guard is a hack - I just found that it worked. About the type intersection operator I don't think there is a notion of commutativity, I suspect it's just the compiler picking the first matching declaration.