为什么泛型在这种情况下不起作用?

问题描述 投票:0回答:2

我是 TypeScript 的新手,我正在将它与 React 一起用于实际项目。

我看到一篇文章,作者指出了使用 Typescript 在 React 中声明条件属性的两种方法。

作者指出了使用 TypeScript 在 React 中声明条件属性的两种方法。

我尝试了使用泛型的解决方案(因为我想以这种方式处理它),并且在检查经过身份验证的道具是否为 true 后,我没有收到 TypeScript 警告我应该是名为“level”的道具的类型。

这是代码:

type Props<T extends boolean> = {   
  authenticated: T;   
  level: T extends true ? 'basic' | 'admin' : 'guest'
}; 

const User = <T extends boolean>(props: Props<T>) => { 
  if (props.authenticated) { 
    return <>Profile ({props.level})</>; } 
  return <>{props.level}</> 
};
javascript reactjs typescript generics
2个回答
0
投票

这就是你现在拥有的:

type Props<T extends boolean> = {   
  authenticated: T;   
  level: T extends true ? 'basic' | 'admin' : 'guest'
}; 

const User = <T extends boolean>(props: Props<T>) => { 
  return props.level 
}

const guestUser = User({ authenticated: false, level: 'guest' }); // guest
const basicUser = User({ authenticated: true, level: 'basic' });  // basic
const adminUser = User({ authenticated: true, level: 'admin' });  // admin

console.log(guestUser);
console.log(basicUser);
console.log(adminUser);

您应该定义两种不同的用户类型,然后创建一个可区分的联合:

type AuthenticatedUser = {
  authenticated: true;
  level: 'basic' | 'admin';
};

type GuestUser = {
  authenticated: false;
};

type UserProps = AuthenticatedUser | GuestUser;

const User = <T extends UserProps>(props: T) => {
  return 'level' in props ? props.level : 'guest';
}

const guestUser = User({ authenticated: false }); // guest
const basicUser = User({ authenticated: true, level: 'basic' });  // basic
const adminUser = User({ authenticated: true, level: 'admin' });  // admin

以下是将上述类型应用到组件的方法:

type AuthenticatedUser = {
  authenticated: true;
  level: 'basic' | 'admin';
};

type GuestUser = {
  authenticated: false;
};

type UserProps = AuthenticatedUser | GuestUser;

const User = <T extends UserProps>(props: T) => {
  if (!props.authenticated) {
    return <>Guest</> 
  }
  return <>Profile ({props.level})</>; } 
}

0
投票

谢谢大家的回复!

最后,我找到了一种更适合我的情况的方法。我决定使用分布式条件类型:https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types

这是结果代码:

 type Props<T extends boolean> = T extends unknown ? {   
      authenticated: T;   
      level: T extends true ? 'basic' | 'admin' : 'guest'
    } : never; 

const User = <T extends boolean>(props: Props<T>) => { 
  if (props.authenticated) { 
    return <>Profile ({props.level})</>; } 
  return <>{props.level}</> 
};

现在 Typescript 知道,当经过身份验证时,

true
level
属性只能是
basic
admin

由于这个答案,我采用了这种方式:https://github.com/microsoft/TypeScript/issues/58224#issuecomment-2060905027

© www.soinside.com 2019 - 2024. All rights reserved.