Deixe-me explicar. Tenho o seguinte caso de uso: No Angular, estou usando um componente de UI de tabela, que se parece com o seguinte:
<my-table [values]="myTableValues">
<my-column field="firstColumn" />
</my-table>
myTableValues
tem um tipo para suas linhas (vamos chamá-lo de myTableValuesRowType
) que é gerado por meio de um gerador de código swagger. Como você vê, o field
pega uma string como valor, o que o torna menos restrito ao tipo.
Eu criei uma solução que cria um objeto do tipo com as mesmas propriedades e retorna o valor string de cada chave. Então, basicamente, algo assim:
[Key]: KeyString
Este é meu código:
type NonNullableKeys<T> = {
[K in keyof T]: T[K] extends null | undefined ? never : K;
}[keyof T];
export type PropertiesOf<T> = Record<NonNullableKeys<T>, string>;
export function getTypeProperties<T>(): PropertiesOf<T> {
return new Proxy({}, {
get: (_target, prop: string) => prop,
}) as PropertiesOf<T>;
}
Exemplo de playground datilografado
Isso torna mais fácil para nós tornar a propriedade field
no modelo HTML mais restrita ao tipo. Pode não ser a melhor solução, mas é a melhor/mais fácil solução que poderíamos usar agora. Exemplo de uso:
//component.ts
readonly rowProperties = getTypeProperties<myTableValuesRowType>();
//component.html
<my-table [values]="myTableValues">
<my-column [field]="rowProperties.firstColumn" />
</my-table>
Dessa forma, se o tipo gerado alterar as chaves de propriedade, eu conseguiria detectá-lo imediatamente.
No entanto, há um problema principal: a função acima não é recursiva. Então, propriedades aninhadas são ignoradas.
Exemplo:
type myTableValuesRowType = {
firstColumn: number;
secondColumn: string;
thirdColumn: number[];
fourthColumn: boolean;
subrow: {
firstSubrowColumn: string;
secondSubrowColumn: number;
}
}
const rowProperties = getTypeProperties<myTableValuesRowType>();
console.log(rowProperties.firstColumn); //returns "firstColumn"
console.log(rowProperties.subrow.firstSubrowColumn); //returns undefined & TS-Error: Property 'firstSubrowColumn' does not exist on type 'string'. expecting to return "subrow.firstSubrowColumn"
Finalmente, minha pergunta seria: como posso torná-lo recursivo? Tentei várias abordagens e fiz algumas pesquisas para encontrar algo semelhante. Tudo o que encontrei foi obter chaves aninhadas em outro tipo , mas não realmente extrair as propriedades e criar um objeto dele.
Para sua informação, não consigo alterar a Biblioteca de Componentes da IU...
Eu apreciaria qualquer ajuda ou informação!
Atualização: Encontrei algo muito parecido , porém ele converte em uma função e não parece tão bom quanto se fosse um objeto.
Outra atualização: esqueci de mencionar que espero rowProperties.subrow.firstSubrowColumn
retornar subrow.firstSubrowColumn
e não apenas a chave filhafirstSubrowColumn