🔎 Search Terms
"exactOptionalPropertyTypes", "strict type equality"
🕗 Version & Regression Information
- Tested in TypeScript 5.8.2
⏯ Playground Link
https://www.typescriptlang.org/play/?exactOptionalPropertyTypes=true#code/PTAEFMA8EMGMBcDyAHeBLA9gO2gGwAoBOGy4h8AngCoWkDOAXAFBOWmhUCMoAvKAN5NQoZMWQB+BqDrxCaLAHMANEwC+rWuA4AmXgKEixk0AFcsAE3AAzeeHOgAPtNnzlajewD6egNoGQoIAy5Bzc0BY6oNCEWrDYdGiW0fYycgi4FBAAjiZ4BgCCdHRk8AA8AKLZeCUGwlxKOgYAfI0qwgFckeFUulFaWBjwoLFY8Yl2oLgYGEXpWTm4+YXFJQByAyUAMlNFFfPVwrWc9d1Nza2g7bpodKD9g9CFaAo4AEa4WvAYIYtF5KvrBXiz2gb3A+wOdQawmaLX8YA610ij2BoNAnyhoEBy0BT1e73BtW0x04pxUAF0ANwsNhaLF-TxUCCQeDgCw3WQmcCNPQANwwCSpAUAvBuAI-2OKkANZor4uBQKMjOVKDGlzPBoSgAOlAAGUMCZCLBwFIABbweDIRggBTq40mF4a2IAW2AAFk0LBiHQMFZ4MAaKRtR60KhgNc6Jy6MBtAB2AAM2gALABiMOcp2O1nwAC0Ce0nAArNoAJwANnzsY8Wl2VQAGvUAJrcngGAAUJSojRbAEpeNzGVAWWzQDXQOJQNwpNoewPWeY6K3252ezw+0zB3PQPXR+PQJOe2OOVopFY8EUDFSVVtpuBq7gSnXN02DD4a2S17Obj562SDGOW1+3xnIcXzfA9CE5XdQBPXAii7Axj1PcBz0rUA1lKAAhd8hxeKZ3jCJ82jAAADW8iNAF5wFgaATCKUAAHcwmVL5oD5BJUPWMIKG5CjXFAIjoKKMiMEIPjDyIgxbxKdD6kPbkgI3Q8am3ASkIOSCW0k6SoMQuTmQ-NFwK0MCIKkLBwB5Mg4OEC9NExZE8TBKgonleB6l1fVDSbUAfHcg1wEAvTgKcwgXNAgyTO0mDwCpIA
💻 Code
// exactOptionalPropertyTypes:typeT1={prop?: string,}typeT2={prop?: undefined|string,}type_=[// ❌ T1 and T2 are considered strictly equalAssert<Equal<T1,T2>>,// T2 is not assignable to T1Assert<Not<Assignable<T1,T2>>>,// T1 is assignable to T2Assert<Assignable<T2,T1>>,// T1 and T2 are not considered loosely equalAssert<Not<LooseEqual<T1,T2>>>,];typeAssert<_Textendstrue>=void;// 🟢 Trick to trigger strict type equality. Source: https://github.com/Microsoft/TypeScript/issues/27024#issuecomment-421529650typeEqual<X,Y>=(<T>()=>TextendsX ? 1 : 2)extends(<T>()=>TextendsY ? 1 : 2) ? true : false;typeLooseEqual<X,Y>=[X]extends[Y]
? ([Y]extends[X] ? true : false)
: false;typeNot<Bextendsboolean>=// `Equal` because want to avoid Not<any> being `false` or `true`Equal<B,true>extendstrue
? false
: (Equal<B,false>extendstrue ? true : never);typeAssignable<Target,Source>=[Source]extends[Target] ? true : false;🙁 Actual behavior
T1 and T2 are considered to be strictly equal – even though T2 is not assignable to T1.
🙂 Expected behavior
T1 and T2 should not be considered strictly equal.
Additional information about the issue
🔎 Search Terms
"exactOptionalPropertyTypes", "strict type equality"
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?exactOptionalPropertyTypes=true#code/PTAEFMA8EMGMBcDyAHeBLA9gO2gGwAoBOGy4h8AngCoWkDOAXAFBOWmhUCMoAvKAN5NQoZMWQB+BqDrxCaLAHMANEwC+rWuA4AmXgKEixk0AFcsAE3AAzeeHOgAPtNnzlajewD6egNoGQoIAy5Bzc0BY6oNCEWrDYdGiW0fYycgi4FBAAjiZ4BgCCdHRk8AA8AKLZeCUGwlxKOgYAfI0qwgFckeFUulFaWBjwoLFY8Yl2oLgYGEXpWTm4+YXFJQByAyUAMlNFFfPVwrWc9d1Nza2g7bpodKD9g9CFaAo4AEa4WvAYIYtF5KvrBXiz2gb3A+wOdQawmaLX8YA610ij2BoNAnyhoEBy0BT1e73BtW0x04pxUAF0ANwsNhaLF-TxUCCQeDgCw3WQmcCNPQANwwCSpAUAvBuAI-2OKkANZor4uBQKMjOVKDGlzPBoSgAOlAAGUMCZCLBwFIABbweDIRggBTq40mF4a2IAW2AAFk0LBiHQMFZ4MAaKRtR60KhgNc6Jy6MBtAB2AAM2gALABiMOcp2O1nwAC0Ce0nAArNoAJwANnzsY8Wl2VQAGvUAJrcngGAAUJSojRbAEpeNzGVAWWzQDXQOJQNwpNoewPWeY6K3252ezw+0zB3PQPXR+PQJOe2OOVopFY8EUDFSVVtpuBq7gSnXN02DD4a2S17Obj562SDGOW1+3xnIcXzfA9CE5XdQBPXAii7Axj1PcBz0rUA1lKAAhd8hxeKZ3jCJ82jAAADW8iNAF5wFgaATCKUAAHcwmVL5oD5BJUPWMIKG5CjXFAIjoKKMiMEIPjDyIgxbxKdD6kPbkgI3Q8am3ASkIOSCW0k6SoMQuTmQ-NFwK0MCIKkLBwB5Mg4OEC9NExZE8TBKgonleB6l1fVDSbUAfHcg1wEAvTgKcwgXNAgyTO0mDwCpIA
💻 Code
🙁 Actual behavior
T1andT2are considered to be strictly equal – even thoughT2is not assignable toT1.🙂 Expected behavior
T1andT2should not be considered strictly equal.Additional information about the issue
exactOptionalPropertyTypesmmkal/expect-type#128