함수가 반환하는 객체 키 및 값에서 문자열 리터럴 유형을 생성하려면 어떻게해야합니까?
Nov 17 2020
읽기 전용 개체에서 유형을 만들려고합니다.
const Actions = {
'user.crud': ['user.create', 'user.read', 'user.update', 'user.delete'],
} as const
type ActionsType = keyof typeof Actions | typeof Actions[keyof typeof Actions][number]
위의 내용은 훌륭하게 작동하며 유형 ActionsType
을 문자열 리터럴 ( 'user.crud', 'user.create'등)로 설정합니다.
그러나 Actions
위 의 객체는 매우 단순합니다. 대신 함수를 통해 액션을 생성해야합니다. 위의 내용을 함수에 의해 생성되도록 이식 할 때, 즉
// set up a function to generate all actions for the passed role
function getActions (role: string): Record<string, string[]> {
return {
[`${role}.crud`]: [`${role}.create`, `${role}.read`, `${role}.update`, `${role}.delete`],
}
}
// generate the Actions from a function
const ActionsFromFunction = {
...getActions('user'),
} as const
// set up the Actions from a readonly object with values generated by getActions()
type ActionsFromFunctionType = keyof typeof ActionsFromFunction | typeof ActionsFromFunction[keyof typeof ActionsFromFunction][number]
유형 ActionsFromFunctionType
이 더 이상 문자열 리터럴로 설정되지 않습니다. 대신 다음으로 설정되고 string | number
문자열이 허용되면 유형 테스트가 실패합니다.
위의 데모를 모았습니다.
운동장
Actions
유형 내에서 문자열 리터럴을 유지하면서 함수를 통해 객체를 생성하는 방법이 있습니까?
답변
2 Temoncher Nov 17 2020 at 14:06
목표는 typescript 템플릿 리터럴 유형 을 통해서만 달성 할 수 있습니다 . typescript 4.0 에서는 지원되지 않지만 4.1 버전에서는 사용할 수 있습니다.
이것이 typescript 4.1로 할 수있는 방법입니다.
type CrudOperations<ROLE extends string> = [`${ROLE}.create`, `${ROLE}.read`, `${ROLE}.update`, `${ROLE}.delete`];
type GetActionsResult<ROLE extends string> = string extends ROLE // check if we can infer type
? { [k: string]: string[] } // if type is not inferable
: { [K in `${ROLE}.crud`]: CrudOperations<ROLE> }; function getActions<ROLE extends string>(role: ROLE): GetActionsResult<ROLE> { return { [`${role}.crud`]: [`${role}.create`, `${role}.read`, `${role}.update`, `${role}.delete`]
} as GetActionsResult<ROLE>;
}
// falls back to { string: string[] } structure
const actions = getActions('admin' as string);
// generate the Actions from a function
const ActionsFromFunction = {
...getActions('user'),
...getActions('orders'),
}
놀이터 링크
1 bela53 Nov 18 2020 at 10:45
getActions
추론을 통해 명시 적 유형없이 작성할 수도 있습니다 .
function getActions<K extends string>(role: K) {
const actions = {
[`${role}.crud`]: [`${role}.create`, `${role}.read`, `${role}.update`,
`${role}.delete`],
} as const
return actions as Record<K,typeof actions[K]>
}
테스트 :
const ActionsFromFunction = {
...getActions('user'),
}
// { user: readonly ["user.create", "user.read", "user.update", "user.delete"];}
const ActionsFromFunction2 = {
...getActions('user' as string),
}
// { [x: string]: readonly [`${string}.create`, ..., `${string}.delete`]; }
type ActionsFromFunctionType =
| keyof typeof ActionsFromFunction
| typeof ActionsFromFunction[keyof typeof ActionsFromFunction][number]
// "user" | "user.create" | "user.read" | "user.update" | "user.delete"
참고, 그건 getActions
당신의 경우, 정확하지 않을 role
노조가 string
유형 :
const ActionsFromFunction3 = {
...getActions('user' as 'user' | 'admin'),
} // { user: ...; admin: ...; }
필요한 경우 분산 조건부 유형getActions
으로 작성할 수 있습니다 .
return actions as K extends any ? Record<K,typeof actions[K]> : never
const ActionsFromFunction3 = {
...getActions('user' as 'user' | 'admin'),
}
/*
| { user: readonly ["user.create", "user.read", "user.update", "user.delete"];}
| { admin: readonly ["admin.create", "admin.read", "admin.update", "admin.delete"]; }
*/
운동장