typescript - Tipo 'string' não pode ser usado para indexar o tipo 'T'.ts(2536)
Estou recebendo o erro acima em result[key] em
type DataType = Record<string, number>
export function getDifference<T extends DataType>(data1: T, data2: T): T {
const keys = Object.keys(data1)
return keys.reduce<T>((result, key) => {
result[key] = data1[key] - data2[key]
return result
}, {})
}
Como faço para me livrar disso enquanto ainda retorno um tipo genérico T para que as funções consumidoras ainda recebam o tipo correto (em vez de simplesmente mudar T para DataType).
Resposta #1
Você precisa definir o tipo correto para keys, assim como para result[key] e {} manualmente, já que o TypeScript não consegue identificá-los corretamente automaticamente.
type DataType = Record<string, number>
export function getDifference<T extends DataType>(data1: T, data2: T): T {
const keys: (keyof T)[] = Object.keys(data1)
return keys.reduce<T>((result, key) => {
if(typeof data1[key] === "number" && typeof data2[key]) { // Safeguard against object, array, etc. properties
result[key] = data1[key] - data2[key] as T[keyof T]
}
return result
}, {} as T)
}
``
Resposta #2
Para aqueles com o desafio semelhante de transformar um Record<string, string> em vez de Record<string, number>, você precisa de um as extra na atribuição à chave específica. Aqui está o que funciona:
function transformRecords<T extends Record<string, string>>(
records: T
): T {
const keys: (keyof T)[] = Object.keys(records)
return keys.reduce(
(results, key) => {
results[key] = records[key] + ' lol' as T[keyof T]
return results
},
{} as T
)
}
Você pode evitar o as extra se retornar um novo objeto em vez de mutar:
function transformRecords<T extends Record<string, string>>(
records: T
): T {
const keys: (keyof T)[] = Object.keys(records)
return keys.reduce(
(results, key) => ({
...results,
[key]: records[key] + 'lol',
}),
{} as T
)
}
E se você estiver transformando com promessas:
async function transformRecords<T extends Record<string, string>>(
records: T
): Promise<T> {
const keys: (keyof T)[] = Object.keys(records)
return await keys.reduce(
async (results, key) => ({
...await results,
[key]: records[key] + 'lol'
}),
Promise.resolve({} as T)
)
}
