Búsqueda de sitios web

javascript - función compatible con TS de 'coalescencia nula'


Estoy intentando hacer funcionar una 'función de fusión nula' en TS. Básicamente get(obj, 'key1', 'key2', 'key3')

Esto es lo que tengo:

const X = {
    a: 42,
    b: 'bar',
    c: {
        d: 'foo'
    }
}

function get<T, K extends keyof T>(item: T, key: K, ...more: string[]): T[K] | null {
  if (key in item) {
    const out = item[key];
    if (more.length) {
      return get(out, more[0], ...more.slice(1));
    } else {
      return out;
    }
  } else {
    return null;
  }
}

const foo = get(X, 'c', 'd');

Esto funciona a nivel superior, por ejemplo get(X, 'c'), pero falla en la recursión por alguna razón que no puedo entender. Lo que sea que intente, obtengo varios errores de TS que más o menos dicen que no puedo convertir una cadena a keyof T[K], ¡aunque eso es exactamente lo que estoy haciendo la primera vez que lo llamo!

¡ayuda!

[editar] ¡Así que esto funciona, pero es feo como el demonio! ¡Alguien ayúdemeeeeee!

function get<T, K extends keyof T>(item: T, key: K): T[K] | null;
function get<T, K extends keyof T, L extends keyof T[K]>(item: T, key1: K, key2: L): T[K][L] | null;
function get<T, K extends keyof T, L extends keyof T[K], M extends keyof T[K][L]>(item: T, key1: K, key2: L, key3: M): T[K][L][M] | null;
function get(obj, key, ...moreKeys) {
  ...

Respuesta #1

Actualmente, en TypeScript no es posible expresar rutas de tipos profundas como estás intentando lograr. Hay un problema en GitHub que discute posibles soluciones similares a la tuya. También hay una propuesta que sugiere la palabra clave "pathof" para resolver exactamente este problema.

Mientras tanto, parece que tendrás que definir tus tipos de manera exhaustiva hasta X niveles como lo has hecho en tu edición.