Open mattaiod opened 1 year ago
give type parameter to O.getWithDefault. like
O.getWithDefault\<number>(0).
@JUSTIVE Yes, I'm familiar with this solution, but I'd like to know if there's a way to improve this function to have this default behavior.
@mattaiod you're issue above is because O.getWithDefault
expects 0
to be an Option<number>
type but it is a literal integer, take a look at the signature for why the non-curried version works:
export declare function getWithDefault<A>(option: Option<A>, defaultValue: NonNullable<A>): A;
export declare function getWithDefault<A>(defaultValue: NonNullable<A>): (option: Option<A>) => A;
As you see, the function would explicitly type A
as 0
in the curried version whereas it would resolve to just number
in the other, because normally the curried value would be within the pipe already and that would define the type. Basically don't use the curried version outside of a pipe/flow sequence OR type it yourself.
Note, there are a lot of instances where you need to do this when using getWithDefault. For example, the following would be a type error because the default is never[]
pipe(O.fromNullable([1, 2, 3]), O.getWithDefault([]))
How about making the default type an extended type of the given T type when it's curried?
I just made a proof-of-concept version of this.
https://www.typescriptlang.org/play?strictNullChecks=false&jsx=0&ts=5.4.0-dev.20240121#code/JYWwDg9gTgLgBAbzMMBTANAeQL5wGZQQhwBEAAiBAEbAA2AngPQwDOAtFarTCQFAz00cTGBjAIAOwA8AFQB8cALxwZcAD5wJAV1q11cLRIAmqPMAmojvXo0YBjLVCioJ8UGFqoQLmAEMxkryoAB6QsHB2kizwAOaoMADqwDAAFgAipr468MqycgAUJnhZ3ABqvrRaqABcAHKStTq0vlSeeQCUigXB1SIB0vKdcrxwo3DBAPw9RSUw5ZWo1rZghJAslnDunt6u-uISQaHQ8JES0XBxicnpmdkATEpwsugAGnAhMC5GLHD1Eo26FpteSKP4A5qtVB5AozbLzKrVF5DfI9Pr7DpdEZjSbTW5lCpVawCIQASU+xGUJF8JH0JCoNLUJDsfBs9kczlcm3A2x8e0CyDQ+SxmAAdABlIiofJUkjtdCs0YAPQmWMuSVSGWK2WlzPaWNsyt4etZKwgaw2Wy8vP6vAFUuF4slUjJXgKMrlCrghtGauumtmdx1stZhvaQA
Maybe the NoInfer
utility type from the Typescript 5.4.0 would be solution for this.
updated example above, seems just working as intended
Hello everyone, first : thanks for this incredible library, look like the best in functionnal programmin in Ts
In the basic example
I have an typescript error at the last line:
The only way I have to fix that is to explicit precise the type like: O.getWithDefault(0 as number)(res) // → 30
The version not curried works:
O.getWithDefault(res, 0)
I guess it's not normal so what is the reason and the solution?
Here my .eslintrc :
{ "extends": "@antfu", "plugins": [ "functional" ], "rules": { "@typescript-eslint/quotes": 0, "no-console": "off", "array-callback-return": "error", "no-constructor-return": "error", "no-duplicate-imports": "off", "no-new-native-nonconstructor": "error", "no-self-compare": "error", "no-template-curly-in-string": "error", "no-unused-private-class-members": "error", "class-methods-use-this": "error", "consistent-return": "error", "default-case": "error", "dot-notation": "error", "eqeqeq": "error", "init-declarations": "error", "no-eq-null": "error", "no-extend-native": "error", "no-implicit-coercion": "error", "@typescript-eslint/no-unused-vars": "off", "no-implicit-globals": "error", "no-new": "error", "no-new-func": "error", "no-new-object": "error", "no-var": "error", "prefer-object-spread": "error", "require-await": "error", "yoda": "error", "explicit-function-return-type": "off" } }
tsconfig.json:
{ "compilerOptions": { "noUnusedLocals": true, "noUnusedParameters": true, "baseUrl": ".", "module": "ESNext", "target": "ESNext", "lib": [ "DOM", "ESNext", "WebWorker" ], "strict": true, "esModuleInterop": true, "jsx": "preserve", "skipLibCheck": true, "moduleResolution": "node", "resolveJsonModule": true, "incremental": false, "noImplicitOverride": true, "noImplicitAny": true, "noImplicitThis": true, "strictFunctionTypes": true, "alwaysStrict": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "useUnknownInCatchVariables": true, "allowUnusedLabels": false, "allowUnreachableCode": false, "noUncheckedIndexedAccess": true, "noPropertyAccessFromIndexSignature": true, "noFallthroughCasesInSwitch": true, "exactOptionalPropertyTypes": true, "noImplicitReturns": true, "strictNullChecks": true, "allowJs": false, "forceConsistentCasingInFileNames": true, "types": [ "vitest", "vite/client", "vue/ref-macros", "vite-plugin-pages/client", "vite-plugin-vue-layouts/client", ], "paths": { "~/": [ "src/" ] } }, "exclude": [ "dist", "node_modules", "cypress", "auto-imports.d.ts" ] }
Thank you in advance for your attention