Búsqueda de sitios web

Typescript seleccionar de argumento de función


En TypeScript, ¿hay una manera de que useContext dentro de lo siguiente seleccione y devuelva el tipo de valor del Provider?

function Provider<Props = {value: number}>(props: Props) { }
function useContext<Value>(context: Context<Value>): Pick<Value, 'value'> { return 0 }

De manera que "Consumidor" devolverá el tipo: número cuando se use de la siguiente manera

function Consumer<Props>(props: Props) { return useContext(Provider) }

...Para contexto adicional:

interface Component<Props = {}> { (props: Properties<Props>): Node }
interface Context<Value> extends Component<{value: Value}> {}

O alternativamente, dado

function Provider({value, children}: {value: string, children: any}) {
  return h(Context, {value: 'value'}, children)
}

const value = useContext(Provider)

¿Cómo se atribuiría la constante "value" al "value" que se encuentra en el objeto {value: 'value'} suponiendo que la función "h" devuelve una interfaz:

interface {type: Context, props: {value: 'value}, children: children}

He intentado usar Pick, props> donde Type es "Provider" y luego usar Pick del resultado de ese Pick, props>, 'value'>.

Sin embargo, eso no parecía funcionar.

Respuesta #1

Hay una forma ingeniosa de extraer tipos de propiedades llamada 'tipos de búsqueda' (Notas de TypeScript 2.1). La sintaxis es:

MyType['value'] // number

Donde MyType contiene una propiedad value: number.

Editar: Estoy teniendo problemas para seguir tu ejemplo, intenté expandir el parámetro 'context' de useContext y terminé con esto:

   function useContext<Value>(context: Context<Value>): Pick<Value, 'value'>;
=> function useContext<Value>(context: Component<{value: Value}>): Pick<Value, 'value'>
=> function useContext<Value>(context: (props: Properties<{value: Value}>) => Node): Pick<Value, 'value'>

Si seguimos el tipo Value hasta la tercera expansión, vemos que no hay ninguna restricción; nada que le diga al compilador que el tipo Value debe tener una propiedad 'value'. La única manera de que el compilador de Typescript devuelva un tipo de useContext(...) basado en Value["value"] es si hay alguna restricción que le indique al compilador que 'value' existe en el tipo.

Una opción, si agregas una restricción de tipo <Props extends {value: number}={value: number}> a Component y Provider, el compilador podrá inferir que props tiene una propiedad 'value'.

Otra opción, indicar explícitamente al compilador qué propiedad ya sabes que existe usando keyof y pasando la cadena literal de la clave (se añadió el parámetro 'key' y se cambió el tipo de retorno a Pick<Value, K>):

function useContext<Value, K extends keyof Value>(context: Context<Value>, key: K): Pick<Value, K> {
  // ...
}

var value = useContext(Provider, 'value');