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
Semi related to a random thought here in that more complicated guards could express codependency of properties:
interfaceArray<T>{length: number;pop(): this.length>0 ? T : undefined;}constarr=[1,2,3];if(arr.length>0){constval=arr.pop();// val is number, not number | undefined under strictNullChecks}
Reacted by Kei Son, Matt Mazzola, Anton Dyshkant, Max Heiber, Marek Lukáš, František Žiačik and Travis Martin
Would this also fix issues with Map?
In the case where you're using map to add memoization to functions there is a similar need to use the ! operator.
constcache=newMap<number,string[]>()if(cache.has(n)){returncache.get(n)!// The if statement above should make return type `string[]` instead of `string[] | undefined`}
Reacted by Adrian Delgado, Łukasz Jagodziński, abuco, Marek Lukáš, František Žiačik, Matthieu Riegler, jiaSheng, Travis Martin and Zefir
exportclassMaybe<T>{constructor(publicvalue: T|undefined){}hasValue(): this is this &{value: T}{returnthis.value!==undefined;}}///////declarevarx: Maybe<string>;if(x.hasValue()){x.value.toLowerCase();}
Matt Mazzola (@mattmazzola) I've used the above technique to describe a way that Map#has could work similarly, but it can get a bit messy.
Reacted by Asad Saeeduddin, Aluan Haddad, Jan Hartigan and Abiria
Ok, I'll have to learn/explore more about the this type guards. In my Map example this type definition is pre-defined by the lib.d.ts since they're part of ES2016 I believe and I didn't want to re-write my own type which wraps the native one.
exportclassMaybe<T>{constructor(publicvalue: T|undefined){}hasValue(): this is this &{value: T}{returnthis.value!==undefined;}}///////declarevarx: Maybe<string>;if(x.hasValue()){x.value.toLowerCase();}
is that "else" doesn't work:
if(x.hasValue()){x.value.toLowerCase();}else{x.value// x.value is string | undefined instead of undefined}
Is there any way to negate the hasValue() function and get undefined, in this case?
(only for sake of showing some stuff off, don't take it seriously :P)
In a language like TypeScript it's better to write abstractions in something like static-land. If at all one wants to consume it in the class form I wrote a little thing called classFromStaticLand that converts a static land implementation to object-oriented implementation. Here's how you'd use it (taking Sam Grönblom (@sgronblo)'s example)
typeDateInterval=|{start: Date,end: Date}|{start: Date,end: null}const_DateInterval={of: (start: Date,end: Date|null)=>({ start, end })asDateInterval,isOngoing: (t: DateInterval): t is DateInterval&{end: null}=>t.end===null,isFinite: (t: DateInterval): t is DateInterval&{end: Date}=>!_DateInterval.isOngoing(t),toFiniteString: (t: DateInterval)=>{if(_DateInterval.isFinite(t)){return`${t.start.toString()} - ${t.end.toString()}`// no error}thrownewError("This DateInterval is ongoing, cannot convert to finite interval string")}}constDateInterval=classFromStaticLand(_DateInterval,"DateInterval");letx=newDateInterval(newDate(),newDate());console.log(x)if(x.isOngoing()){x.end// null;x.end.getDay()// expected error}else{x.end// Date;console.log(x.end.getDay())}
Activity
kitsonk commentedon Sep 24, 2016
Semi related to a random thought here in that more complicated guards could express codependency of properties:
aluanhaddad commentedon Sep 24, 2016
This would be interesting... expressing path dependent types.Read the OP backward... too early.
mattmazzola commentedon Jul 12, 2017
Would this also fix issues with Map?
In the case where you're using map to add memoization to functions there is a similar need to use the
!operator.DanielRosenwasser commentedon Jul 12, 2017
What about using
thistype guards instead?Matt Mazzola (@mattmazzola) I've used the above technique to describe a way that
Map#hascould work similarly, but it can get a bit messy.mattmazzola commentedon Jul 13, 2017
Ok, I'll have to learn/explore more about the
thistype guards. In my Map example this type definition is pre-defined by the lib.d.ts since they're part of ES2016 I believe and I didn't want to re-write my own type which wraps the native one.masaeedu commentedon Dec 28, 2017
Daniel Rosenwasser (@DanielRosenwasser) Any way to make that approach work for private properties?
sgronblo commentedon Feb 28, 2020
I wanted to use this for this pattern:
https://www.typescriptlang.org/play/?ssl=14&ssc=1&pln=15&pc=1#code/KYDwDg9gTgLgBAYwDYEMDOa4BEU2ASQDs8oA3FJOAbwCg44woBLcvRCQtGKAVwRmgAKRi1zA4XFLABc2MQBoGzVuOCEAJrJxsAPnEI8kSAJTUAvjTpwmaAPKEA5hCaPBx2TAAWN65i8+AMmo4NU19Q0ozait6KGAYHihCOH80ADpQuABeHPCjKwsrGwAxFyY8Nw9vTB9UuCCqEI0tMTgo2npY+MTk1IyNOABCXIN8+kL6AVLCcuAAZW4XBzdozusAMzhBPpKyiuNTDrW4OISkuAADABIqPslYNIEF5ldjKIBaOBu+0MeIZ6WbjMFxibVBXigEAA7vpgDCAKJQSFQQQAcgAKtU5HgiCRyJQfBwnEtFAgUIRCBB4AgOKRgLAUhA4Os9uIXHiKBJFo5UcYCjQzEA
But it gives me the following error: "Property 'end' has conflicting declarations and is inaccessible in type 'DateInterval & { end: Date; }'.(2546)"
rodrigost23 commentedon Sep 5, 2020
The problem with the solution by Daniel Rosenwasser (@DanielRosenwasser):
is that "else" doesn't work:
Is there any way to negate the
hasValue()function and getundefined, in this case?devanshj commentedon Aug 5, 2021
Yep, here's a better version -
devanshj commentedon Aug 5, 2021
(only for sake of showing some stuff off, don't take it seriously :P)
In a language like TypeScript it's better to write abstractions in something like static-land. If at all one wants to consume it in the class form I wrote a little thing called
classFromStaticLandthat converts a static land implementation to object-oriented implementation. Here's how you'd use it (taking Sam Grönblom (@sgronblo)'s example)Here's what the console would look like...

Here's the playground link to try it out.
And here's the full code for reference
But more seriously one way to facilitate this is to allow typing
thisin the constructor like so...The problem is this...