유형 스크립트에서 정규식과 일치하는 문자열 유형을 정의하는 방법은 무엇입니까?
유형 스크립트에서 정규식과 일치하는 문자열 유형을 정의하는 방법은 무엇입니까?
문자열 형식에 대한 정보가 있는 인터페이스를 정의할 수 있습니까? 다음 예를 들어 보겠습니다:
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}`