Как из unknown грамотно вызывать toString?

Хочу написать функцию которая будет возвращать string из неизвестного значения

Так как я не могу знать, что туда положили изначально, но хочу по феншую описать тип, я не использую any, а использую unknown

Но вопрос, как грамотно из него можно вызвать метод toString?

Что бы typescript не ругался

Ошибка при вызове метода из unknown


Ответы (3 шт):

Автор решения: UserTest013

typescript не позволяет вам использовать переменную неизвестного типа, если вы либо не приведете переменную к известному типу, либо не сузите ее тип.

export const intoString = (value: unknown) => (value as any)?.toString?.() ?? '';
→ Ссылка
Автор решения: xydope

Для таких вещей используют не unknown, а дженерики.

Неплохой практикой будет, если вам нужно писать ф-цию, решения которой для вас затруднительно, то начинайте с описания типа функции.

В целом, можно вообще от подобной идеи отказаться и просто использовать String('аргумент')

type SomeToStringFn = <T>(value: T)=>string //тип функции, что-то принимает, возвращает строку.

const convertToString:SomeToStringFn = (value) => String(value) //сама функция.

→ Ссылка
Автор решения: Qwertiy

Сделать можно по-разному, но и результат будет разный: playground

function f1(x: unknown) {
  return "" + x
}

function f2(x: unknown) {
  return String(x)
}

function f3(x: unknown) {
  return `${x}`
}

function f4(x: unknown) {
  return typeof (x as any)?.toString === "function" && (x as any)?.toString() || ""
}

function f5(x: unknown) {
  return Object.prototype.toString.call(x);
}

function f6(x: unknown) {
  return (x as any).toString()
}

function f7(x: unknown) {
  return (x as any)?.toString()
}

const cases = {
  undefined,
  null: null,
  symbol: Symbol(),
  "{ valueOf() { return 88 } }": { valueOf() { return 88 } },
  "() => {}": () => {},
  "{ toString() { return 99 } }": { toString() { return 99 } },
  "Object.create(null)": Object.create(null),
}

const res: { [key: string]: { [key: string]: unknown } } = {}

for (const [name, obj] of Object.entries(cases)) {
  const cur: { [key: string]: unknown } = res[name] = {}
  
  for (const f of [f1, f2, f3, f4, f5, f6, f7]) {
    try {
      cur[f as any] = f(obj)
    } catch (err) {
      cur[f as any] = err
    }
  }
}

console.table(res)

А вот получившаяся таблица:

скриншот таблицы

→ Ссылка