Quando você executa o compilador do TypeScript (tsc
) para transpile código TypeScript em runnable JavaScript, a linguagem de tipo estático do sistema é apagada. Portanto, o seu Foo
tipo (cujo nome foi mudado para letras maiúsculas para atender TS convenções de nomenclatura) não está presente em qualquer formulário em tempo de execução. Não há nada que você pode iterar sobre para obter as chaves go
e start
.
A maneira mais direta de obter algo para acontecer em tempo de execução é escrever o JavaScript necessário para fazê-lo e, em seguida, para se certificar de que o compilador do TypeScript pode dar-lhe o forte tipos que você precisa, enquanto você está escrevendo. Este é basicamente o inverso do que você está tentando fazer.
No seu caso: o que faz generate()
necessárias para trabalhar em tempo de execução? Bem, se podemos assumir que os valores gerados pelo generate()
serão objetos mantendo apenas string
propriedades de valor, é necessário passar uma lista de chaves do objeto. Então, o que se escrevemos generate()
para fazer isso, e, em seguida, definir Foo
em termos de saída de generate()
em vez de outro modo?
Por exemplo:
function generate<K extends PropertyKey>(...keys: K[]) {
return Object.fromEntries(keys.map(k => [k, ""])) as { [P in K]: string };
}
const myFooObject = generate("go", "start");
type Foo = typeof myFooObject;
/* type Foo = {
go: string;
start: string;
} */
console.log(myFooObject)
/* {
"go": "",
"start": ""
} */
Aqui generate()
é uma genérica função que recebe uma lista de chaves (do tipo K
) e produz um valor de um tipo com chaves K
e valores do tipo string
. Que {[P in K]: string}
é um mapeada tipo equivalente a Record<K, string>
usando o Record<K, V>
utilitário tipo.
A implementação usa Object.fromEntries()
para construir o objeto, e o tipo de retorno é afirmado ser o tipo certo porque Transcrito vê Object.fromEntries()
como retornar um tipo que é muito grande para os nossos propósitos.
De qualquer forma, quando você chamar const myFooObject = generate("go", "start")
, ele produz um valor do tipo {go: string; start: string}
, que é o mesmo que o seu Foo
escreva. Então, podemos definir Foo
como type Foo = typeof myFooObject
em vez de fazê-lo manualmente. Você pode ainda fazê-lo manualmente, mas o ponto que eu estou mostrando aqui é que é muito mais fácil para gravação a SECO do código de Máquina, se você começar com valores e gerar tipos deles, em vez de tentar fazer da outra maneira ao redor.
Novamente, se você estiver usando o compilador do TypeScript tsc
como-é e, em seguida, digite o apagamento impede de escrever generate()
a partir da definição de Foo
. Mas...
Se você estiver disposto a adicionar uma etapa de compilação do seu projeto e executar a geração de código usando o compilador do TypeScript API ou algo parecido, em seguida, você pode fazer arbitrário coisas com tipos. Existem bibliotecas que fazem coisas semelhantes ao que você quer; por exemplo, o ts-auto-simulação de créditos para gerar objetos mock dado a um tipo de objeto, que se parece exatamente o seu caso de uso.
Como um extra etapa de compilação pode ser uma abordagem razoável para você, mas se você for por esse caminho, você deve notar que você não está usando simplesmente o TypeScript mais (e, portanto, o tema é, provavelmente, fora do âmbito de uma pergunta com apenas uma Máquina de escrever marca).
Parque infantil link para o código de