如何使用 Typescript 泛型限制对象的允许键?

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

我只想允许一种类型的对象作为函数参数。对象键必须以

$
开头,仅包含字母字符,并且其值必须为
Test
类型。在下面的“示例 1”下,我仅设法限制为
string
类型的键。我在网上找到了一个 DFA 生成器,它可以检查字符串是否以
$
开头(“示例 2”)。如何将这两者结合起来,以便强制对象的键以
$
开头?请注意“示例 3”底部的变量
validKey
invalidKey

// example 1

interface Test {
  testProperty: string;
}

interface TestObject {
  [key: string]: Test;
}

const testObject: TestObject = {
  $prop1: {testProperty: 'test'},
  $prop2: {testProperty: 'test2'},
};

// example 2

type Head<StrT extends string> = StrT extends `${infer HeadT}${string}` ? HeadT : never;

type Tail<StrT extends string> = StrT extends `${string}${infer TailT}` ? TailT : never;

interface Dfa {
  startState: string;
  acceptStates: string;
  transitions: Record<string, Record<string, string>>;
}
type AcceptsImpl<DfaT extends Dfa, StateT extends string, InputT extends string> = InputT extends ''
  ? StateT extends DfaT['acceptStates']
    ? true
    : false
  : AcceptsImpl<DfaT, DfaT['transitions'][StateT][Head<InputT>], Tail<InputT>>;

type Accepts<DfaT extends Dfa, InputT extends string> = AcceptsImpl<
  DfaT,
  DfaT['startState'],
  InputT
>;

interface MyDfa {
  startState: '0';
  acceptStates: '1';
  transitions: {
    '0': Record<'$', '1'> & Record<string, 'fail'>;
    '1': Record<
      | 'A'
      | 'B'
      | 'C'
      | 'D'
      | 'E'
      | 'F'
      | 'G'
      | 'H'
      | 'I'
      | 'J'
      | 'K'
      | 'L'
      | 'M'
      | 'N'
      | 'O'
      | 'P'
      | 'Q'
      | 'R'
      | 'S'
      | 'T'
      | 'U'
      | 'V'
      | 'W'
      | 'X'
      | 'Y'
      | 'Z'
      | 'a'
      | 'b'
      | 'c'
      | 'd'
      | 'e'
      | 'f'
      | 'g'
      | 'h'
      | 'i'
      | 'j'
      | 'k'
      | 'l'
      | 'm'
      | 'n'
      | 'o'
      | 'p'
      | 'q'
      | 'r'
      | 's'
      | 't'
      | 'u'
      | 'v'
      | 'w'
      | 'x'
      | 'y'
      | 'z',
      '1'
    > &
      Record<string, 'fail'>;
    fail: Record<string, 'fail'>;
  };
}

type ValidObjectKey<T extends string> = Accepts<MyDfa, T>;

// example 3

const checkValidObjectKey = <T extends string>(key: T) => {
  return key as ValidObjectKey<T>;
};

const validKey = checkValidObjectKey('$valid'); // validKey is of type "true"
const invalidKey = checkValidObjectKey('invalid'); // invalidKey is of type "false"

typescript dfa
1个回答
0
投票

尝试:

type Test = {
  testProperty: string;
}

type TestObject = Record<`$${string}`, Test>;

const config: TestObject = {
  $a: { testProperty: 'a' },
  $b: { testProperty: 'a' },
};

查看演示

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