TypeScript: функция, возвращающая общий c Type, расширяющий запись - PullRequest
1 голос
/ 05 мая 2020

Я хочу создать функцию parse<Type>(), которая анализирует строку и возвращает объект, но я хочу, чтобы parse() возвращал правильный тип, и мне трудно.

type Identity = {
  name: string;
};

type ContactDetails = {
  phone: string;
  email: string;
};

function parse<T extends Record<string, string>>(input: string): T {
  const result = {};
  input.split('&').forEach(bits => {
    const [name, value] = bits.split('=');
    result[name] = value;
  });
  return result;
}

parse<Identity>('name=Paulin');
parse<ContactDetails>('phone=0123456789&email=paulin@email.com');

Я получаю Ошибка TypeScript:

Тип '{}' не может быть назначен типу 'T'. '{}' можно присвоить ограничению типа 'T', но 'T' может быть создан с другим подтипом ограничения 'Record'. ts (2322)

Я понимаю, в чем проблема is: {} несовместимо с общим типом c Record. Но как я могу это решить?

Большое спасибо!

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Я почти уверен, что это одно из тех мест, где вы должны прибегнуть к утверждению типа. В данном случае:

function parse<T extends Record<string, string>>(input: string): T {
  const result: Record<string, string> = {};
// −−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^
  input.split('&').forEach(bits => {
    const [name, value] = bits.split('=');
    result[name] = value;
  });
  return result as T;
// −−−−−−−−−−−−^^^^^
}

На игровой площадке

Однако важно понимать ограничения здесь. Если ваши типы Identity или ContactDetails имели определенные реализации c (в вашем примере их нет, они просто interface s), возвращаемый объект parse не будет поддерживаться этой реализацией. Это это просто Record<string, string>. Так что вам может быть лучше, если вместо этого parse вернет Record<string, string> и предоставит вызывающей стороне возможность принять обоснованное решение о типе.

0 голосов
/ 06 мая 2020

На основании того, что предложил TJ Crowder: предоставьте вызывающему абоненту право принимать решение о типе. вот моя последняя реализация:

type Identity = {
  name: string;
};

type ContactDetails = {
  phone: string;
  email: string;
};

function parse(input: string): Record<string, string> {
  const result: Record<string, string> = {};
  input.split('&').forEach(bits => {
    const [name, value] = bits.split('=');
    result[name] = value;
  });
  return result;
}

const identity = parse('name=Paulin') as Identity;
const details = parse('phone=0123456789&email=paulin@email.com') as ContactDetails;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...