개발하자

유형 스크립트에서 정규식과 일치하는 문자열 유형을 정의하는 방법은 무엇입니까?

Cuire 2023. 7. 5. 02:30
반응형

유형 스크립트에서 정규식과 일치하는 문자열 유형을 정의하는 방법은 무엇입니까?

문자열 형식에 대한 정보가 있는 인터페이스를 정의할 수 있습니까? 다음 예를 들어 보겠습니다:

interface timeMarkers{
    markerTime: string[]        
};

예를 들어 다음과 같습니다:

{
   markerTime: ["0:00","1:30", "1:48"]                   
}

내 질문: 문자열 값이 단순하다고 선언하고 거기서 시작하는 대신 항상 이 정규식과 일치해야 하는 유형을 정의하는 방법이 있습니까?

var reg = /[0-9]?[0-9]:[0-9][0-9]/;




그런 유형을 정의할 방법이 없습니다. GitHub에는 이를 지원하는 기능이 있지만 현재는 우선순위가 아닌 것으로 보인다. 그것에 대해 투표하면, 아마도 그 팀은 그것을 향후 발표에 포함시킬 것이다.

편집

4.1부터는 실제로 모든 옵션을 정의하지 않고 문자열의 유효성을 검사하는 를 정의할 수 있습니다:

type MarkerTime =`${number| ''}${number}:${number}${number}`

let a: MarkerTime = "0-00" // error
let b: MarkerTime = "0:00" // ok
let c: MarkerTime = "09:00" // ok

놀이터 링크




나도 지금 비슷한 기능을 찾고 있었어!

그리고 나는 결국 이것에 대해 생각하게 되었다: 좀 더 복잡한 개발 환경을 설정하면 이것을 실행할 수 있지 않을까요? 파일 감시기를 사용하여 tsc를 트리거하고 TypeError 이벤트를 검색하여 *d.ts 파일을 업데이트할 수 있습니다.

내 말은 다음과 같은 것을 의미한다:

export type superRegexType = 'type-1' | 'type-2' | '/type-/';

그리고 훅으로서 뭔가(루디컬 제안):

const onTypeError = (err: Error, nameOfTypeSuperRegexType: string) => {
  const myTypesFile = require('fs').readFileSync(`path/to/\*d.ts`) as string;
  const searchFor = `export type ${nameOfTypeSuperRegexType} =`;
  const getDefinition = (inMyTypesFile: string, searchFor: string) => {
    const typeDefinitionString = inMyTypesFile.split(searchFor)[0].split(';')[0] + ';';
    const stringsInThere = typeDefinitionString.split(' | ').map(_str => _str.trim());
    const myRegexStr = stringsInThere.pop();
    return {
      oldTypeDefinitionString: typeDefinitionString,
      stringsInThere,
      myRegexStr,
      myRegex: new RegExp(myRegexStr)
    };
  };
  const myTypeDefinition = getDefinition(myTypesFile, searchFor);

  const shouldDynamicallyAddType = myTypeDefinition.myRegex.exec(err.message);
  if (!shouldDynamicallyAddType) {
    console.log("this is a real TypeError");
    console.error(err);
    return;
  } else {
    const indexInErrMessage = shouldDynamicallyAddType.index;
    const _endIdx = err.message.indexOf('\'');
    const typeToAdd = err.message.slice(indexInErrMessage, _endIdx).trim();
    myTypeDefinition.stringsInThere.push(typeToAdd);
    const updatedTypeDefinitionString = `${searchFor} ${myTypeDefinition.stringsInThere.join(' | ')} ${myTypeDefinition.myRegexStr};`;
    myTypesFile.replace(myTypeDefinition.oldTypeDefinitionString, updatedTypeDefinitionString);
    // --> save that new d.ts and return hopefully watch the lint-error disappearing
  }
}

아마도 이런 종류의 솔루션을 사용하면 컴파일 시간에 ReGEx를 기반으로 동적으로 유형을 추가할 수 있습니다.

당신은 어떻게 생각하나요?




다음 코드를 브라우저 웹 콘솔에 붙여넣습니다: TS에서 유형으로 사용할 수 있는 생성된 결과:


@bela53의 답을 기반으로 하지만 훨씬 더 단순하다. 우리는 @Titian과 비슷하지만 단점이 없는 매우 간단한 해결책을 수행할 수 있다:

type HourPrefix = '0'|'1'|'2';
type MinutePrefix = HourPrefix | '3'|'4'|'5';
type Digit = MinutePrefix |'6'|'7'|'8'|'9';

type Time = `${HourPrefix | ''}${Digit}:${MinutePrefix}${Digit}`

const validTimes: Time[] = ["00:00","01:30", "23:59", "16:30"]
const invalidTimes: Time[] = ["30:00", "23:60", "0:61"] // all emit error



경고: TypeScript가 접근 방식으로 처리할 수 있는 것에는 한계가 있습니다...

를 기반으로 IPv4 주소에 대해 다음과 같은 유형 정의를 시도했습니다. 이 정의는 유형 스크립트 오류를 무시하고 여전히 유효하다는 전제 하에 어쨌든 빌드하려고 했을 때 IntelliJ가 많은 CPU 시간을 소비하게 했습니다(결국에는 IntelliJ를 죽이고 다시 시작해야 했습니다).

type segment = '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'10'|'11'|'12'|'13'|'14'|'15'|'16'|'17'|'18'|'19'|'20'|'21'|'22'|'23'|'24'|'25'|'26'|'27'|'28'|'29'|'30'|'31'|'32'|'33'|'34'|'35'|'36'|'37'|'38'|'39'|'40'|'41'|'42'|'43'|'44'|'45'|'46'|'47'|'48'|'49'|'50'|'51'|'52'|'53'|'54'|'55'|'56'|'57'|'58'|'59'|'60'|'61'|'62'|'63'|'64'|'65'|'66'|'67'|'68'|'69'|'70'|'71'|'72'|'73'|'74'|'75'|'76'|'77'|'78'|'79'|'80'|'81'|'82'|'83'|'84'|'85'|'86'|'87'|'88'|'89'|'90'|'91'|'92'|'93'|'94'|'95'|'96'|'97'|'98'|'99'|'100'|'101'|'102'|'103'|'104'|'105'|'106'|'107'|'108'|'109'|'110'|'111'|'112'|'113'|'114'|'115'|'116'|'117'|'118'|'119'|'120'|'121'|'122'|'123'|'124'|'125'|'126'|'127'|'128'|'129'|'130'|'131'|'132'|'133'|'134'|'135'|'136'|'137'|'138'|'139'|'140'|'141'|'142'|'143'|'144'|'145'|'146'|'147'|'148'|'149'|'150'|'151'|'152'|'153'|'154'|'155'|'156'|'157'|'158'|'159'|'160'|'161'|'162'|'163'|'164'|'165'|'166'|'167'|'168'|'169'|'170'|'171'|'172'|'173'|'174'|'175'|'176'|'177'|'178'|'179'|'180'|'181'|'182'|'183'|'184'|'185'|'186'|'187'|'188'|'189'|'190'|'191'|'192'|'193'|'194'|'195'|'196'|'197'|'198'|'199'|'200'|'201'|'202'|'203'|'204'|'205'|'206'|'207'|'208'|'209'|'210'|'211'|'212'|'213'|'214'|'215'|'216'|'217'|'218'|'219'|'220'|'221'|'222'|'223'|'224'|'225'|'226'|'227'|'228'|'229'|'230'|'231'|'232'|'233'|'234'|'235'|'236'|'237'|'238'|'239'|'240'|'241'|'242'|'243'|'244'|'245'|'246'|'247'|'248'|'249'|'250'|'251'|'252'|'253'|'254'|'255';
export type ipAddress = `${segment}.${segment}.${segment}.${segment}`;

나는 이것에 대한 해결책이 있는지 확실하지 않다.




type D1 = 0|1;
type D3 = D1|2|3;
type D5 = D3|4|5;
type D9 = D5|6|7|8|9;

type Hours = `${D9}` | `${D1}${D9}` | `2${D3}`;
type Minutes = `${D5}${D9}`;
type Time = `${Hours}:${Minutes}`;

및 에서 아이디어를 수집하는 콤팩트 솔루션입니다.

이 솔루션에는 시간 유형에 대한 2039개의 열거 멤버가 있습니다.

츠 운동장




나의 2센트


type digit01 = '0' | '1';
type digit03 = digit01 | '2' | '3';
type digit05 = digit03 | '4' | '5';
type digit09 = digit05 | '6' | '7' | '8' | '9';

type minutes = `${digit05}${digit09}`;
type hour = `${digit01 | ''}${digit09}` | `2${digit03}`;

type MarkerTime = `${hour}:${minutes}`;

const ok: Record<string, MarkerTime> = {
  a: '0:00',
  b: '09:00',
  c: '23:59',
};

const notOk: Record<string, MarkerTime> = {
  a: '0-00',
  b: '24:00',
  c: '93.242:942.23',
};




MySQL 날짜/시간 문자열의 경우

나는 MySQL datetime 문자열 값을 반영하는 유형을 만들려고 했다. ie "2022-07-31 23:11:54.

흥미롭게도, 당신은 현재 그것을 거의 할 수 있지만, 만약 당신이 더 구체적인 것을 추가한다면 그것은 아무 것이나 되거나 더 이상 타이핑을 추가할 수 없다고 불평할 것이다. 나는 그것이 만들 수 있는 타이핑의 수에는 한계가 있다고 생각한다?

type OneToNine = 1|2|3|4|5|6|7|8|9
type ZeroToNine = 0|1|2|3|4|5|6|7|8|9

export type DateTimeType = `${
  `${number}`
}-${
  `0${OneToNine}` | `1${0|1|2}`
}-${
  `0${OneToNine}` | `1${ZeroToNine}` | `2${ZeroToNine}` | `3${0|1}`
} ${
  `0${OneToNine}` | `1${0|OneToNine}` | `2${0|1|2|3}`
}:${number}:${number}`



@bela53의 답변을 보완하기 위해, 그 사용은 형식 구성에 사용될 수 있다.

const hours = [
  '00' , '01', '02', '03', '04', '05', '06', '07', '08',
  '09' , '10', '11', '12', '13', '14', '15', '16', 
  '17' , '18', '19', '20', '21', '22', '23'
] as const

type HH = typeof hours[number]

const minutes = [
  '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', 
  '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', 
  '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', 
  '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', 
  '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', 
  '50', '51', '52', '53', '54', '55', '56', '57', '58', '59'
] as const 

type MM = typeof minutes[number]

type Time = `${HH}:${MM}`

반응형