Cuando se ejecuta el Manuscrito compilador (tsc
) para transpile Manuscrito código ejecutable de JavaScript, el lenguaje es estático y que tipo de sistema se borran. Por lo que su Foo
tipo (cambia a mayúsculas para satisfacer TS convenciones de nomenclatura) no está presente en cualquier formulario en tiempo de ejecución. No hay nada que usted puede iterar a través de obtener las llaves go
y start
.
La forma más sencilla de conseguir que algo suceda en el tiempo de ejecución es escribir el código JavaScript necesario para hacerlo, y para asegurarse de que el Manuscrito compilador puede dar el fuerte de tipos que necesita mientras está escribiendo. Esta es básicamente la inversa de lo que estamos tratando de hacer.
En tu caso: ¿qué generate()
para trabajar en tiempo de ejecución? Así, si asumimos que los valores generados por generate()
serán objetos de la celebración de sólo string
valores de las propiedades, entonces tenemos que pasar una lista de las claves del objeto. ¿Qué tal si escribimos generate()
para hacer eso, y luego definir Foo
en términos de la salida de generate()
en lugar de que sea al revés?
Por ejemplo:
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": ""
} */
Aquí generate()
es un genérico función que toma una lista de claves (de tipo K
) y produce un valor de un tipo con claves en K
y los valores de tipo string
. Que {[P in K]: string}
es un asignada tipo equivalente a Record<K, string>
el uso de la Record<K, V>
tipo de utilidad.
La aplicación utiliza Object.fromEntries()
para construir el objeto, y el tipo de retorno es afirmado ser el tipo correcto porque Manuscrito ve Object.fromEntries()
como devolver un tipo que es demasiado amplia para nuestros propósitos.
De todos modos cuando te llame const myFooObject = generate("go", "start")
produce un valor de tipo {go: string; start: string}
, que es el mismo que el de su Foo
tipo. Así que podemos definir Foo
como type Foo = typeof myFooObject
en lugar de hacerlo manualmente. Usted puede hacerlo manualmente, pero el punto que estoy mostrando aquí es que es mucho más fácil escribir en SECO de código en la Máquina si usted comienza con los valores y generar tipos de ellos, en lugar de tratar de hacerlo de la otra manera alrededor.
De nuevo, si usted está utilizando el Manuscrito del compilador tsc
como-es, entonces, el tipo de borrado le impide escribir generate()
a partir de la definición de Foo
. Pero...
Si usted está dispuesto a añadir un paso de compilación para su proyecto y realizar la generación de código mediante el Manuscrito compilador API o algo por el estilo, a continuación, puede hacer cosas arbitrarias con tipos. Hay bibliotecas que hacer cosas similares a lo que usted desea; por ejemplo, ts-auto-simulacro de reclamaciones para generar objetos ficticios dado un tipo de objeto, que se parece exactamente el caso de uso.
Un extra construir paso podría ser un enfoque razonable para usted, pero si vas por ese camino debe tener en cuenta que no estás usando simplemente el Manuscrito más (y por lo tanto el tema es, probablemente, fuera del ámbito de una pregunta con sólo un Manuscrito de la etiqueta).
Patio enlace a código