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
namespaceround_one{// let's start with declaring a function that:// - accepts a numeric `primaryProperty`// - accepts `dependentProperty` which should be identical to `primaryProperty`// - accepts optional `dependentFunctionProperty` which is a function with a parameter based on `primaryProperty`declarefunctiondefine<constobjextends{readonlyprimaryProperty: numberdependentProperty: obj['primaryProperty']dependentFunctionProperty?: (primary: obj['primaryProperty'])=>void}>(obj: obj): obj// so far everything works as expecteddefine({primaryProperty: 11,dependentProperty: 11,// no errors})define({primaryProperty: 11,dependentProperty: 13,// an error})define({primaryProperty: 11,dependentProperty: 11,dependentFunctionProperty: ()=>{},// no errors if there is no parameter})// but when we add a parameter to `dependentFunctionProperty`, it breaks because...define({primaryProperty: 11,dependentProperty: 11,// Type '(primary: number) => void' is not assignable to type '(primary: unknown) => void'. // though we didn't state which type we expect in the parameter! and why did `primary` become `unknown`?dependentFunctionProperty: (primary)=>{primary},})}namespaceround_two{// if we replace a function property with a method, things get even weirder.declarefunctiondefine<constobjextends{readonlyprimaryProperty: numberdependentProperty: obj['primaryProperty']dependentMethod(primary: obj['primaryProperty']): void}>(obj: obj): objdefine({primaryProperty: 11,dependentProperty: 11,dependentMethod(primary){// `primary` is not inferred as `unknown` now, but still is not `11`: it's a `number`primary},})// but we can manually annotate `primary` without any problems// which would be impossible for "normal" function signatures expecting `number`define({primaryProperty: 11,dependentProperty: 11,dependentMethod(primary: 11){// no errorsprimary},})// annotating `primary` with something different than 11 results in an error as welldefine({primaryProperty: 11,dependentProperty: 11,dependentMethod(primary: 12){// an errorprimary},})}namespaceround_three{// now we get to the weirdest part of the problem.// accidentally i've discovered that simply repeating// the declaration of `define` makes typescript behave almost correctlydeclarefunctiondefine<constobjextends{readonlyprimaryProperty: numberdependentProperty: obj['primaryProperty']dependentFunctionProperty?: (primary: obj['primaryProperty'])=>void}>(obj: obj): objdeclarefunctiondefine<constobjextends{readonlyprimaryProperty: numberdependentProperty: obj['primaryProperty']dependentFunctionProperty?: (primary: obj['primaryProperty'])=>void}>(obj: obj): objdefine({primaryProperty: 11,dependentProperty: 11,// no errors here, but hovering over `primary` shows `number` as if we were declaring `dependentFunctionProperty` as a methoddependentFunctionProperty: (primary)=>{primary},})// annotating `primary` works like in `dependentMethod` as welldefine({primaryProperty: 11,dependentProperty: 11,dependentFunctionProperty: (primary: 11)=>{// no errorsprimary},})define({primaryProperty: 11,dependentProperty: 11,dependentFunctionProperty: (primary: 12)=>{// an errorprimary},})}
π Actual behavior
I'm not sure where to begin. Properties of a type parameter that reference other properties of the same type parameter seem to be completely untested in TypeScript.
In the example above, I have referenced a generic's property from other properties in three ways:
from a function property
from a method
from a function property, but declaration of the function is duplicated!
All of them are buggy, but in different ways.
π Expected behavior
Speaking honestly, I was expecting from such dependent properties to not work at all, failing with some kind of circular constraint error, but now I believe they could become usable some day.
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered:
TS inference algorithm can't always unify everything in ways you'd like it to when some information is missing. It has to deduce it after all and sometimes it might fail. That's why you see different results when you annotate that parameter vs when you don't. With annotated parameters, TS is able to infer some things earlier - in a single inference pass.
I'm surprised by the different behavior of your arrow function vs method examples. Both are context-sensitive and I'd expect them to behave roughly the same way in this context.
That said, your first example can be fixed if you use a reverse-mapped type (TS playground):
namespaceround_four{declarefunctiondefine<constobjextends{readonlyprimaryProperty: number;dependentProperty: obj["primaryProperty"];dependentFunctionProperty?: (primary: obj["primaryProperty"])=>void;},>(obj: {[Kinkeyofobj]: obj[K]}): obj;define({primaryProperty: 11,dependentProperty: 11,// no errors});define({primaryProperty: 11,dependentProperty: 13,// an error});define({primaryProperty: 11,dependentProperty: 11,dependentFunctionProperty: ()=>{},// no errors if there is no parameter});define({primaryProperty: 11,dependentProperty: 11,dependentFunctionProperty: (primary)=>{primary;// nicely inferred as 11, even when `primary` parameter isn't annotated},});}
Thank you! Should this issue be closed as not planned now? I still wonder why redeclaration has effect on the types, though at this point that is not a practical interest
π Search Terms
generics, type parameters, dependent properties
π Version & Regression Information
None of the versions I have tried work as expected.
β― Playground Link
https://www.typescriptlang.org/play/?ts=5.1.6#code/HYQwtgpgzgDiDGEAEAnA9gV2AEwPpuGQG8AoJcpAekqQBsIAXAciiSgZBQaQHcBLBgAskIJADMs8BnwJIhIBgC4yFakgC0I+IhgNWo4Bkgo+8JAAMYJsJwCeABXQwIXW+ZXk1mhDr0XsEM44EMAMjmjOrua8gqbCUIKYtNhIAEbIfAGhpiC0cmgWVnw2KA5OLgxuHlQ03tqBfhHSBLn+gSFZDABiks3A4ZGV0Tyx8MJ8+uK9MsC8AsKicCjgjC5pIFAQKbKW1nYDFVUUSAHwtJzIEsBSMycQYnyEADzwBOxIaKkAVkgQAB4MDqsUjHY4oCAgbAEWi2JBFEplCKHRRIQxgdIoarHAJBToHVwoz5fADaTHh+3KriYAF0sRQcR0Qt1pgR8ZUAPwogAU5NKhO+pN5iMGthpAEokABeAB8SAAbmhMtUAL7SrlE-lfMWapAkapqKAFMScX5yly2ISPADmvDQKAA1vpWP9nFIttUAg9CFykCDQeQhWzbCiAIwhgA0dPIDOCoSDoYjNVRBRc6BQUBVSDFHvujwgPr9-sDlMqCcj-uj7VjYRLwaQIYAzOGkyBZqm7Zns9jc97fVG4XtSvH6xH+zG8bWy2Oq50etc+sOuRKZb7lc21MAUyg06w+GI5IIXBlWJu4ZwVoDMcdlVm9cc1KkMNwRiFeMhISlFufIJf8m1cUyc43KytbmM2AhpOCICOmkEDwCAGCbAAdChOZevmfYVgOxQUkiBIjuWFbjkyw5hoR-pqAAKrYzhIEwPKDnWaIYsusoKpkTBIBMybcBsUB8FaoCpPQf6VLR9FCiiWD2puPDAKx8qKtgTBIbqWFqEImBWsIPDINgmTAEw3DsAoyAjHEcg0WZyAunB3CPAeyBLBeLgAIQiDgMSwvpKS7DhpTROkryQBY0mycA5jstOAGhEBC6TkgDH+bYCmFlh2EIv2a6diQyp6qAkCwAgyDoFgeAMDwBRpWoe5vqggTnIgIhTPOtxWHhlRzEIzU-ok2DNpawBWqwVqMKar66XwKABCgSE5mcFwtcBsyenmLxvNwRK-ACQKYRWUFQsAMIZbhIoosxLjRYycYJUSgqMUGNJXdWACyjB9UlCKavdyWPdS2qKUq15qhqHzfADW13vSPYYWlxzFh1dZkc9E6I1OWHEaEb2adgn12BKcMVmofkItE3GbvZwBiKmWwiKw5hhWgcnRLJzaPsZ0i0Hk5NoNw5hhuYKICCwzXmBdKDuOlFBCll5FIDe2b6jQ7N1fBsw2IYuTHa2FOmYUjHDPMmC8cAsLtcJEBgBm940OZYy2hgySwVxYAwGgUD8Rb4h2kgABEm4oDYtC+0tfRsAJoAMBg4LOn8rrSENFji5L0PoQW-YI2dBEoyRCXIxjM5MtjH2SSOBNJqe7bpv28OMbLOVKx5usJzaJN2Ib3WGr11onHu1PgqEB6tiO9VQI7fgOcPVd02+XNoXm6dYZnyLZwXMU1mjq9EYXWPvWguOlyGABM5dqFP24dlLAZ11h2XXreeUkAV0BwE1pU4LgQjgsQjeyXVo3cAYAUIQ1kpoBHeEsTa+4QEDk+PQMAc0bZaHgJkJkWtYR8CYGaXuUBXhmnBCkeQxligwGOuCZwChrSNxgacc4yww5oH3OYVahBog2HtNASyzhcEmF0LBQQIBsG5DAO7bgrxtx2RhPNOhlwWQrRhutYA7wtr-EBDgYE-YDrQjNg9BK4sc43U3ndMkujEZPTXtdZkrUQKI05IlUuxjl5Un+lKNiSkVQg2+JqCG3xpGLSuMtO46FFHKO+NtNR2ANFYS0UdHRv09FGAxAYjeWdHGmJFOY7e684ozCDHYvGfIwYkhMfEsxLiVzsWwB49UXiik+J+FDSsac9pFnSSvfOWTLGkVHOpGglcL7piQIecEbMnxDLQPgnuEy1htwCmwRIPB6bJxnrVXSb5wR3AWiYROzCd5WOWkGaIGwep7yqRY6sOSbFZwKSlVxLT0oy1vnLBWjSWzAGbj3WZbhbQOlYLQPgHCuKzF2evYu+8jmsF0nPbszTCbX1KVnDp-pMYpPaT0zpFy5GLkPiGVKFctw7hrtLG+FY74UBeTChe9za4IrRXLbs69un0uhtkrFCUbmhhPncogbzfgDKJfCzKTycrKiAA
π» Code
π Actual behavior
I'm not sure where to begin. Properties of a type parameter that reference other properties of the same type parameter seem to be completely untested in TypeScript.
In the example above, I have referenced a generic's property from other properties in three ways:
All of them are buggy, but in different ways.
π Expected behavior
Speaking honestly, I was expecting from such dependent properties to not work at all, failing with some kind of circular constraint error, but now I believe they could become usable some day.
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: