TypeScript:返回扩展记录的泛型类型的函数<;字符串,字符串>;

TypeScript:返回扩展记录的泛型类型的函数<;字符串,字符串>;,typescript,generics,Typescript,Generics,我想创建一个parse()函数来解析字符串并返回一个对象,但是我想parse()返回正确的类型,我正在努力 type Identity = { name: string; }; type ContactDetails = { phone: string; email: string; }; function parse<T extends Record<string, string>>(input: string): T { const result

我想创建一个
parse()
函数来解析字符串并返回一个对象,但是我想
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');

类型标识={
名称:字符串;
};
类型ContactDetails={
电话:字符串;
电子邮件:字符串;
};
函数解析(输入:字符串):T{
const result={};
input.split('&').forEach(位=>{
常量[名称,值]=位。拆分('=');
结果[名称]=值;
});
返回结果;
}
解析('name=Paulin');
解析('电话=0123456789&电子邮件=paulin@email.com');
我得到一个TypeScript错误:

类型“{}”不可分配给类型“T”。 “{}”可分配给“T”类型的约束,但“T”可以用约束“Record”的不同子类型实例化。ts(2322)

我了解问题所在:
{}
与泛型
记录
类型不兼容。但我怎么才能解决这个问题呢


多谢各位

我相当肯定这是您必须求助于类型断言的地方之一。在这种情况下:

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;
// −−−−−−−−−−−−^^^^^
}
函数解析(输入:字符串):T{
常量结果:记录={};
// −−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^
input.split('&').forEach(位=>{
常量[名称,值]=位。拆分('=');
结果[名称]=值;
});
将结果返回为T;
// −−−−−−−−−−−−^^^^^
}


不过,理解这里的局限性很重要。如果您的
Identity
ContactDetails
类型有特定的实现(在您的示例中没有,它们只是
interface
s),则该实现不会支持对象
parse
返回。它只是一条
记录
。因此,您最好让
解析
返回一条
记录
,然后让调用者根据T.J.Crowder的建议做出明智的决定。

根据T.J.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;

类型标识={
名称:字符串;
};
类型ContactDetails={
电话:字符串;
电子邮件:字符串;
};
函数解析(输入:字符串):记录{
常量结果:记录={};
input.split('&').forEach(位=>{
常量[名称,值]=位。拆分('=');
结果[名称]=值;
});
返回结果;
}
const identity=parse('name=Paulin')作为标识;
const details=parse('电话=0123456789&电子邮件=paulin@email.com")作为联络详情;;

返回任意结果我希望调用方按照您所说的那样做出决定,这就是我希望使用的原因。但我明白,在这种情况下,最好使用
作为
,因此:
const identity=parse('name=Paulin')作为标识
@PaulinTrognon-我想是的,但我的打字教育还只是走了这么远。您的另一个选项是上面的
const identity=parse('name=Paulin')在这两种情况下,调用方都显式地这样做,这对我来说很重要。