te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>typescript - Why isn’t my conditional key remapping filtering out keys with attribute: true? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

typescript - Why isn’t my conditional key remapping filtering out keys with attribute: true? - Stack Overflow

programmeradmin3浏览0评论

I’m trying to create a mapped type that filters out object keys based on the value of a boolean property in a class. I have the following code:

class Test {
  readonly attribute: boolean;

  constructor(attribute?: boolean) {
    this.attribute = attribute ?? true;
  }
}

type TestType2<T extends Record<string, Test>> = {
  [K in keyof T as T[K]['attribute'] extends true ? never : K]: number;
};

const a = {
  test1: new Test(),
  test2: new Test(false),
};

type FinalTest = TestType2<typeof a>;

I expected FinalTest to be { test2: number } since test1 is constructed with the default attribute (i.e., true), and only test2 (with attribute equal to false) should remain. However, the resulting type is { test1: number, test2: number }.

Why does the conditional type T[K]['attribute'] extends true ? never : K not filter out test1 as expected? Is it an issue with how the class property is typed, or is there another approach to achieve the desired filtering? Any insights would be appreciated!

Thank you!

I’m trying to create a mapped type that filters out object keys based on the value of a boolean property in a class. I have the following code:

class Test {
  readonly attribute: boolean;

  constructor(attribute?: boolean) {
    this.attribute = attribute ?? true;
  }
}

type TestType2<T extends Record<string, Test>> = {
  [K in keyof T as T[K]['attribute'] extends true ? never : K]: number;
};

const a = {
  test1: new Test(),
  test2: new Test(false),
};

type FinalTest = TestType2<typeof a>;

I expected FinalTest to be { test2: number } since test1 is constructed with the default attribute (i.e., true), and only test2 (with attribute equal to false) should remain. However, the resulting type is { test1: number, test2: number }.

Why does the conditional type T[K]['attribute'] extends true ? never : K not filter out test1 as expected? Is it an issue with how the class property is typed, or is there another approach to achieve the desired filtering? Any insights would be appreciated!

Thank you!

Share Improve this question asked Feb 18 at 1:26 machadinhosmachadinhos 133 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

The reason test1 is not filtered out is that the type of attribute is evaluated at the time of type definition:

class Test {
  readonly attribute: boolean;
  // ...
}

At that time, attribute is simply of type boolean, which means TypeScript cannot determine whether it is true or false based on the constructor's input. Which means, no keys will be filtered out because boolean cannot extend true or false.

To achieve the desired filtering, you can use generic types like this:

class Test<Attr extends boolean = true> {
  readonly attribute: Attr;

  constructor(attribute: Attr = true as any) {
    this.attribute = attribute;
  }
}

type TestType2<T extends Record<string, Test<boolean>>> = {
  [K in keyof T as T[K]['attribute'] extends true ? never : K]: number;
};

const a = {
  test1: new Test(),
  test2: new Test(false),
};

type FinalTest = TestType2<typeof a>; // { test2: number }

TS Playground for the solution

Now, the type of attribute is evaluated when you instantiate the Test class. If you don't pass any argument to the constructor, the type will default to true; otherwise, it will be inferred from the provided attribute. This allows TypeScript to correctly filter out keys based on the actual value of attribute.

Just make sure that the Attr default type matches the attribute default value.

发布评论

评论列表(0)

  1. 暂无评论