Closed marceleq27 closed 3 years ago
Hi, The problem arise from conversion of name
to actionName
. As you see the type of name
and actionName
is string not a literal string type. You need something like this:
function createRequestAction<T extends string>(name: T) {
const actionName: F<T> = ...
return {
[`${actionName}Success`]: createActionCreator(`${name}_SUCCESS`),
[`${actionName}Error`]: createActionCreator(`${name}_ERROR`),
[`${actionName}Done`]: createActionCreator(`${name}_DONE`),
}
}
The F
type level function converts input literal type to your desired output literal type.
Hi, thank you for your suggestions, I've tried to type this but it still doesn't work and I don't know how to fix this
type ActionStringType<S extends string, D extends string> = string extends S
? ""
: S extends ""
? ""
: S extends `${infer T}${D}${infer U}`
? `${Lowercase<T>}${Capitalize<ActionStringType<U, D>>}`
: Capitalize<Lowercase<S>>
const createRequestAction = <T extends string>(name: T) => {
const actionName = name
.split("_")
.map((item, i) => {
if (i === 0) {
return item.toLowerCase()
}
return item.charAt(0).toUpperCase() + item.slice(1).toLowerCase()
})
.join("") as ActionStringType<T, "_">
return {
[`${actionName}Success`]: createActionCreator(`${name}_SUCCESS`),
[`${actionName}Error`]: createActionCreator(`${name}_ERROR`),
[`${actionName}Done`]: createActionCreator(`${name}_DONE`),
}
}
I've made a ActionStringType
and for example:
type S1 = ActionStringType<"SET_AS_FAVOURITE">
// returns "setAsFavourite" which is good
So this type is working fine but TS is still not seeing the names (keys of object) of action creators.
And for example now something like ...createRequestAction("SET_AS_FAVOURITE")
returns:
const createRequestAction: <"SET_AS_FAVOURITE">(name: "SET_AS_FAVOURITE") => {
[x: string]: ExactActionCreator<"SET_AS_FAVOURITE_SUCCESS", () => {
type: "SET_AS_FAVOURITE_SUCCESS";
}> | ExactActionCreator<"SET_AS_FAVOURITE_ERROR", () => {
...;
}> | ExactActionCreator<...>;
}
I want to change this [x: string]
to something like S1 type returns
Unfortunately, TS doesn't have a nice sync between type-level and term-level, which will becomes its biggest regret soon. :)
So in simple terms, the compiler is dumb and the good news is that you as a human being are smart. Just shut the compiler mouth up with any
type and calculate the output type on your own bare foot. (SPOILER ALERT! Maintenance burden; but it works!)
function f<a extends string>(a: a): Output<a> {
// ...
return { ... } as any
}
Hmm, i think it won't work because I can't use ActionStringType
type as a value in object, I mean can't do something like this:
type Output<T> = {
[key: `${ActionStringType}Success`<T, "_"> ]: AnyAction
[key: `${ActionStringType}Error`<T, "_"> ]: AnyAction
[key: `${ActionStringType}Done`<T, "_"> ]: AnyAction
}
Please attach more code if you have some idea, i can test it ;)
type Types = "Success" | "Error" | "Done"
type Output<a> = {
[key in `${SnakeCaseToCamelCase<a>}${Types}`]: AnyAction
}
I figured it out and thats work :)
type Types = "Success" | "Error" | "Done"
type SnakeToCamelCase<S extends string> = S extends `${infer T}_${infer U}` ? `${Lowercase<T>}${Capitalize<Lowercase<SnakeToCamelCase<U>>>}` : S
type Output<T extends string> = {
[key in `${SnakeToCamelCase<T>}${Types}`]: AnyAction
}
I've attached code, maybe somebody also need it. Thank you very much again for help :)
Hello, I want to generate a few side actions and I wrote a generator function but TS still complaining :) Here is a small example:
For example:
createRequestAction("SET_AS_FAVOURITE")
generate object with{ setAsFavouriteSuccess: ActionType, setAsFavouriteError: ActionType, setAsFavouriteDone: ActionType }
and I'm exporting actions like this:
And now in reducer, TS doesn't recognize names like
actions.setAsFavouriteSuccess
, is there a way to type this function correctly?Thanks :)