Pesquisa de site

Objeto é do tipo 'unknown' em genéricos do TypeScript


Eu tenho uma função simples que recebe uma função como argumento e retorna uma nova função. Eu recebo Object é do tipo 'unknown' ao chamar a função retornada

const makeFunction = <T>(callback: (someParam: number, options: T) => any) => {

  return (options: T) => {
    const param = 4;

    return callback(param, options)  
  }  
}

O código acima está ok para TypeScript, mas quando estou chamando a função, recebo uma reclamação

makeFunction((param, options) => {
  const a = options.optionsValue //(parameter) options: unknown,  Object is of type 'unknown'
})({optionsValue: 'some value'})

Resposta #1

Como este é o primeiro resultado que você obtém ao pesquisar no Google Object is of type 'unknown', quero postar meu caso. Pode ajudar leitores futuros. Esta não é a resposta à pergunta do OP.

Eu recebi este erro no bloco catch. Depois de depurar por um tempo, descobri que a partir do TypeScript v4.0, as variáveis da cláusula catch têm o tipo unknown em vez de any.

E de acordo com os documentos:

desconhecido é mais seguro do que qualquer tipo porque nos lembra que precisamos realizar algum tipo de verificação antes de operar sobre nossos valores.

Meu código parecia algo assim antes da versão 4.0:

try {
  // try something exceptional here
} catch (error) {
  console.log(error.message);
}

E para corrigir esse erro, tive que colocar uma verificação adicional if na variável error.

try {
  // try something exceptional here
} catch (error) {
  let errorMessage = "Failed to do something exceptional";
  if (error instanceof Error) {
    errorMessage = error.message;
  }
  console.log(errorMessage);
}

Resposta #2

atualizar meu tsconfig.json com o seguinte funcionou para mim:

"useUnknownInCatchVariables": false,

Atualização :

você precisa colocá-lo assim sob compilerOptions

"compilerOptions": {
    "useUnknownInCatchVariables": false
  }

Nota: Você precisa do Typescript v4.4 ou superior para poder usar esta opção do compilador, caso contrário receberá um erro de compilação.

npm install -g ts-node@latest

npm install -g typescript@latest

Resposta #3

Eu tive esse problema em um try/catch ao atualizar o Typescript para a versão 4.4 e encontrei na documentação a explicação para isso.

Em resumo, eles adicionaram a flag useUnknownInCatchVariables que é verdadeira por padrão se strict. Basicamente, ela muda o tipo do erro em um catch de any para unknown, causando esse problema.

Então, para atualizar para 4.4, você tem algumas opções:

try {
    ...
} catch(e) {
    console.log((e as Error).message)
}

ou :

try {
    ...
} catch(e) {
    if (e instanceof Error) {
        console.log(e.message)
    }
}

ou no seu tsconfig.json você pode definir explicitamente a flag como false:

{
    "compilerOptions": {
        "strict": true,
        "useUnknownInCatchVariables": false
    }
}

Resposta #4

Você pode usar casting: (err as Error)

Eu gosto da solução com a declaração if, mas isso também funciona:

catch (error) {
  let msg = (error as Error).message;
}

Resposta #5

Precisamos pensar em como o TS pode inferir o tipo a partir desta definição. O TS pode entender o tipo a partir de dois lugares:

  • conjunto de tipo genérico explícito
  • tipo do segundo argumento da função

No seu caso de uso, você não fornece o tipo em nenhum desses lugares e essa é a razão pela qual você recebe unknown, porque o TypeScript não pode saber qual tipo de argumento você precisa. Para dar ao TypeScript a possibilidade de entender o tipo, você pode fazer o seguinte:

Definir explicitamente genérico por:

makeFunction<YourType>((param, options) => {...))

Defina o tipo na função de callback, por exemplo, definindo um anteriormente:

const f = (a: number, b: {a: string}) => b // here types are set
makeFunction(f)({a: 'some value'}) // makeFunction is able to infer the types by f

Você também pode fazer isso inline dizendo ((param: number, options: MyType))

Responda após o comentário se options pode ser dinâmico

Acredito que você queira o seguinte comportamento:

const makeFunction = <F extends (someParam: number, options: any) => any>(callback: F) => {

  return (options: Parameters<F>[1]) => {
    const param = 4;

    return callback(param, options)  
  }  
}
const f = (a: number, b: {a: string}) => b
makeFunction(f)({ a: 'a' })
const g = (a: number, b: {b: number}) => b
makeFunction(g)({b: 1})

Nós dizemos poucas coisas:

  • F agora é uma função que se estende de uma função binária, e inferimos diretamente seu tipo
  • Parameters<F>[1] é o tipo do segundo argumento da função dada F

Resposta #6

Problema com TS 4.0 explicado aqui: https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/#unknown-on-catch

Todas as outras respostas não funcionaram para mim, mas usar o isAxiosError funcionou muito bem:

   } catch (error) {
      if (axios.isAxiosError(error)) {
        const errResp = error.response;
        // Handle your error type safe here
      } else {
        // Handle the unknown
      }
    }

Sem o erro Object is of type 'unknown'.ts(2571) anymore.

Artigos relacionados